📄 wave.c
字号:
/* * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Multimedia * FILE: lib/wdmaud/wave.c * PURPOSE: WDM Audio Support - Wave Device / Header Manipulation * PROGRAMMER: Andrew Greenwood * UPDATE HISTORY: * Nov 18, 2005: Created */#include <windows.h>#include "wdmaud.h"const char WAVE_PREPARE_DATA_SIG[4] = "WPPD";/* OBSOLETE CODE - FOR REFERENCE ONLY*/#if 0MMRESULT OpenWaveDevice( CHAR device_type, DWORD device_id, LPWAVEOPENDESC open_details, DWORD flags, DWORD user_data){ MMRESULT result = MMSYSERR_ERROR; WCHAR* device_path; PWDMAUD_DEVICE_INFO device; ASSERT( open_details ); ASSERT( open_details->lpFormat ); if ( device_id > 100 ) return MMSYSERR_BADDEVICEID; /* Not sure about this */ device_path = (WCHAR*) open_details->dnDevNode; device = CreateDeviceData(device_type, device_id, device_path, TRUE); if ( ! device ) { DPRINT1("Couldn't create device data\n"); result = MMSYSERR_NOMEM; goto cleanup; } device->type = device_type; device->id = device_id; device->flags = flags; /* We don't deal with this here */ if ( flags & WAVE_FORMAT_QUERY ) { result = QueryWaveFormatSupport(device, open_details); DeleteDeviceData( device ); return result; } device->state->device_queue_guard = AllocMem(sizeof(CRITICAL_SECTION)); if ( ! device->state->device_queue_guard ) { DPRINT1("Couldn't allocate memory for queue critical section (error %d)\n", (int) GetLastError()); result = MMSYSERR_NOMEM; goto cleanup; } /* Initialize the critical section */ InitializeCriticalSection(device->state->device_queue_guard); /* We need these so we can contact the client later */ device->client_instance = open_details->dwInstance; device->client_callback = open_details->dwCallback; /* Reset state */ device->state->current_wave_header = NULL; device->state->unknown_24 = 0; device->state->is_running = FALSE; device->state->is_paused = device->type == WDMAUD_WAVE_IN ? TRUE : FALSE; DPRINT("Opening the device\n"); result = OpenDeviceViaKernel(device, open_details->lpFormat); if ( result != MMSYSERR_NOERROR ) { DPRINT1("Couldn't open! mmsys error %d\n", (int) result); /* TODO: WAVERR_BADFORMAT translation ? */ goto cleanup; } /* Enter the critical section while updating the device list */ EnterCriticalSection(device->state->device_queue_guard); /* ... */ LeaveCriticalSection(device->state->device_queue_guard); /* The wave device handle is actually our structure. Neat, eh? */ open_details->hWave = (HWAVE) device; /* We also need to set our "user data" for winmm */ LPVOID* ud = (LPVOID*) user_data; /* FIXME */ *ud = device; if ( device->client_callback ) { DWORD message; message = (device->type == WDMAUD_WAVE_IN ? WIM_OPEN : WOM_OPEN); DPRINT("About to call the client callback\n"); /* Call the callback */ NotifyClient(device, message, 0, 0); DPRINT("...it is done!\n"); } result = MMSYSERR_NOERROR; cleanup : { if ( result != MMSYSERR_NOERROR ) if ( device ) DeleteDeviceData(device); return result; }}#endifMMRESULT CloseWaveDevice( PWDMAUD_DEVICE_INFO device){ MMRESULT result = MMSYSERR_ERROR; result = ValidateDeviceData(device, TRUE); if ( result != MMSYSERR_NOERROR ) { DPRINT1("Device data invalid\n"); return MMSYSERR_INVALPARAM; } if ( ! IsWaveDeviceType(device->type) ) { DPRINT1("Invalid device type (expected a WAVE device)\n"); return MMSYSERR_INVALPARAM; } /* TODO: Perform actual close */ if ( device->state->current_wave_header ) { DPRINT1("Can't close! Device is still playing\n"); return WAVERR_STILLPLAYING; } /* TODO */ /* DestroyCompletionThread(device); - check result */ result = CallKernelDevice(device, IOCTL_WDMAUD_CLOSE_DEVICE, 0, 0); if ( result != MMSYSERR_NOERROR ) { DPRINT1("Close failed! mmsyserr %d\n", (int) result); return result; /* TODO: convert? */ } if ( device->client_callback ) { DWORD message; message = (device->type == WDMAUD_WAVE_IN ? WIM_CLOSE : WOM_CLOSE); DPRINT("About to call the client callback\n"); /* Call the callback */ NotifyClient(device, message, 0, 0); DPRINT("...it is done!\n"); } /* TODO: Enter critical section Loop through device list until we reach the end or until we find a pointer matching "device". Leave critical section Delete critical section ... */ DeleteDeviceData(device); return MMSYSERR_NOERROR;}/* ValidateWaveHeaderPreparation Overview : First, check to see if we can write to the buffer given to us. Fail if we can't (invalid parameter?) Make sure the signature matches "WPPD". Fail if not (invalid param?) Finally, validate the "overlapped" member, by checking to see if that buffer is writable, and ensuring hEvent is non-NULL.*/MMRESULT ValidateWavePreparationData(PWDMAUD_WAVE_PREPARATION_DATA prep_data){ /* UNIMPLEMENTED */ return MMSYSERR_NOERROR;}/* ValidateWaveHeader Checks that the header memory can be written to, that the flags are valid (using the mask 0xFFFFFFE0), and that the wave preparation data is valid. Returns MMSYSERR_NOERROR if all's well, or MMSYSERR_INVALPARAM if not.*/MMRESULT ValidateWaveHeader(PWAVEHDR header){ DWORD flag_check; if ( IsBadWritePtr(header, sizeof(WAVEHDR)) ) { DPRINT1("Bad write pointer\n"); return MMSYSERR_INVALPARAM; } flag_check = header->dwFlags & 0xffffffe0; /* FIXME: Use flag names */ if ( flag_check ) { DPRINT1("Unknown flags present\n"); return MMSYSERR_INVALPARAM; } return ValidateWavePreparationData( (PWDMAUD_WAVE_PREPARATION_DATA) header->reserved);}/* PrepareWaveHeader Checks the parameters are sane, allocates memory for a WAVEPREPAREDATA structure and also memory for an OVERLAPPED structure. After this, an un-named event is created (as hEvent of the OVERLAPPED) structure, and the WAVEPREPAREDATA structure has its signature set accordingly. Returns MMSYSERR_NOTSUPPORTED so that winmm does further processing.*/MMRESULT PrepareWaveHeader( PWDMAUD_DEVICE_INFO device, PWAVEHDR header){ MMRESULT result = MMSYSERR_ERROR; PWDMAUD_WAVE_PREPARATION_DATA prep_data = NULL; DPRINT("PrepareWaveHeader called\n"); /* Check the device data is valid */ result = ValidateDeviceData(device, TRUE); if ( result != MMSYSERR_NOERROR ) { DPRINT1("Bad device info or device state\n"); return result; } /* Make sure we were actually given a header to process */ if ( ! header ) { DPRINT1("Bad header\n"); return MMSYSERR_INVALPARAM; } /* NOTE: At this point, what happens if not prepared or already queued? */ header->lpNext = NULL; header->reserved = 0; /* Allocate memory for the wave preparation data */ prep_data = (PWDMAUD_WAVE_PREPARATION_DATA) AllocMem(sizeof(WDMAUD_WAVE_PREPARATION_DATA)); if ( ! prep_data ) { DPRINT1("Couldn't lock global memory for preparation data (error %d)\n", (int)GetLastError()); result = MMSYSERR_NOMEM; goto fail; } /* Create an event */ prep_data->overlapped = AllocMem(sizeof(OVERLAPPED)); if ( ! prep_data->overlapped ) { DPRINT1("Couldn't allocate memory for overlapped structure (error %d)\n", (int)GetLastError()); result = MMSYSERR_NOMEM; goto fail; } prep_data->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if ( ! prep_data->overlapped->hEvent ) { DPRINT1("Creation of overlapped event failed (error %d)\n", (int)GetLastError()); result = MMSYSERR_NOMEM; goto fail; } /* Copy the signature over and tie the prepare structure to the wave header */ memcpy(prep_data->signature, WAVE_PREPARE_DATA_SIG, 4); header->reserved = (DWORD) prep_data; /* We return this so WINMM can do further processing */ result = MMSYSERR_NOTSUPPORTED; return result; fail : { if ( prep_data ) { if ( prep_data->overlapped ) { if ( prep_data->overlapped->hEvent ) CloseHandle(prep_data->overlapped->hEvent); /* ok? */ FreeMem(prep_data->overlapped); } FreeMem(prep_data); } return result; }}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -