📄 sndwin.cpp
字号:
// --------------------------------------------------------------------------// Name: sndwin.cpp// Purpose:// Date: 08/11/1999// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000// CVSID: $Id: sndwin.cpp,v 1.12 2005/09/23 12:47:52 MR Exp $// wxWindows licence// --------------------------------------------------------------------------#include "wx/wxprec.h"#ifdef __WINDOWS__#ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/app.h" #include "wx/string.h"#endif#include "wx/module.h"#include "wx/msw/private.h"// -------------------------------------------------------------------------// MMedia headers// -------------------------------------------------------------------------#include "wx/mmedia/sndbase.h"#include "wx/mmedia/sndwin.h"#include "wx/mmedia/sndpcm.h"// -------------------------------------------------------------------------// System headers// -------------------------------------------------------------------------#include <windows.h>#include <mmsystem.h>// -------------------------------------------------------------------------// External definitions, forward, ...// -------------------------------------------------------------------------typedef struct _wxSoundInternal wxSoundInternal;typedef struct _wxSoundInfoHeader wxSoundInfoHeader;extern const wxChar *wxCanvasClassName;wxList *wxSoundHandleList = NULL;static inline wxSoundStreamWin *wxFindSoundFromHandle(WXHWND hWnd){ wxObjectList::compatibility_iterator node = wxSoundHandleList->Find((long)hWnd); if (!node) return NULL; return (wxSoundStreamWin *)node->GetData();}struct _wxSoundInternal { HWND m_sndWin; HWAVEIN m_devin; HWAVEOUT m_devout; bool m_output_enabled, m_input_enabled;};struct _wxSoundInfoHeader { HGLOBAL m_h_header, m_h_data; char *m_data; WAVEHDR *m_header; int m_mode; bool m_playing, m_recording; wxUint32 m_position, m_size; wxSoundStreamWin *m_driver;};#define WXSOUND_MAX_QUEUE 10wxSoundStreamWin::wxSoundStreamWin(){ wxSoundFormatPcm pcm; m_production_started = false; m_internal = new wxSoundInternal; if (!m_internal) { m_snderror = wxSOUND_MEMERROR; m_internal = NULL; return; } m_snderror = wxSOUND_NOERROR; // Setup defaults CreateSndWindow(); SetSoundFormat(pcm); m_internal->m_input_enabled = false; m_internal->m_output_enabled = false; m_waiting_for = false; if (!OpenDevice(wxSOUND_OUTPUT)) { m_snderror = wxSOUND_NOERROR; //next call to OpenDevice won't do this if (!OpenDevice(wxSOUND_INPUT)) return; } CloseDevice();}wxSoundStreamWin::~wxSoundStreamWin(){ if (m_internal) { if (m_production_started) StopProduction(); DestroySndWindow(); delete m_internal; }}// -----------------------------------------------------------------------// _wxSoundHandlerWndProc: Window callback to handle buffer completion// -----------------------------------------------------------------------LRESULT APIENTRY _EXPORT _wxSoundHandlerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM WXUNUSED(lParam)){ wxSoundStreamWin *sndwin; sndwin = wxFindSoundFromHandle((WXHWND)hWnd); if (!sndwin) return (LRESULT)0; switch (message) { case MM_WOM_DONE: sndwin->NotifyDoneBuffer(wParam, wxSOUND_OUTPUT); break; case MM_WIM_DATA: sndwin->NotifyDoneBuffer(wParam, wxSOUND_INPUT); break; default: break; } return (LRESULT)0;}// -----------------------------------------------------------------------// CreateSndWindow() creates an hidden window which will receive the sound// events// -----------------------------------------------------------------------void wxSoundStreamWin::CreateSndWindow(){ FARPROC proc = MakeProcInstance((FARPROC)_wxSoundHandlerWndProc, wxGetInstance()); // NB: class name must be kept in sync with wxCanvasClassName in // src/msw/app.cpp! m_internal->m_sndWin = ::CreateWindow(wxT("wxWindowClass"), NULL, 0, 0, 0, 0, 0, NULL, (HMENU) NULL, wxGetInstance(), NULL); GetLastError(); ::SetWindowLong(m_internal->m_sndWin, GWL_WNDPROC, (LONG)proc); // Add this window to the sound handle list so we'll be able to redecode // the "magic" number. wxSoundHandleList->Append((long)m_internal->m_sndWin, (wxObject *)this);}// -----------------------------------------------------------------------// DestroySndWindow() destroys the hidden window// -----------------------------------------------------------------------void wxSoundStreamWin::DestroySndWindow(){ if (m_internal->m_sndWin) { ::DestroyWindow(m_internal->m_sndWin); wxSoundHandleList->DeleteObject((wxObject *)this); }}// -------------------------------------------------------------------------// OpenDevice(int mode) initializes the windows driver for a "mode"// operation. mode is a bit mask: if the bit "wxSOUND_OUTPUT" is set,// the driver is opened for output operation, and if the bit "wxSOUND_INPUT"// is set, then the driver is opened for input operation. The two modes// aren't exclusive.// The initialization parameters (sample rate, ...) are taken from the// m_sndformat object.// At the end, OpenDevice() calls AllocHeaders() to initialize the Sound IO// queue.// -------------------------------------------------------------------------bool wxSoundStreamWin::OpenDevice(int mode){ wxSoundFormatPcm *pcm; WAVEFORMATEX wformat; if (!m_sndformat) { m_snderror = wxSOUND_INVFRMT; return false; } pcm = (wxSoundFormatPcm *)m_sndformat; wformat.wFormatTag = WAVE_FORMAT_PCM; wformat.nChannels = pcm->GetChannels(); wformat.nBlockAlign = wformat.nChannels * pcm->GetBPS() / 8; wformat.nSamplesPerSec = pcm->GetSampleRate(); wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign; wformat.wBitsPerSample = pcm->GetBPS(); wformat.cbSize = 0; // ----------------------------------- // Open the driver for Output operation // ----------------------------------- if (mode & wxSOUND_OUTPUT) { MMRESULT result; result = waveOutOpen(&m_internal->m_devout, WAVE_MAPPER, &wformat, (DWORD)m_internal->m_sndWin, 0, CALLBACK_WINDOW); if (result != MMSYSERR_NOERROR) { m_snderror = wxSOUND_INVDEV; return false; } m_output_frag_out = WXSOUND_MAX_QUEUE-1; m_current_frag_out = 0; m_internal->m_output_enabled = true; } // ----------------------------------- // Open the driver for Input operation // ----------------------------------- if (mode & wxSOUND_INPUT) { MMRESULT result; result = waveInOpen(&m_internal->m_devin, WAVE_MAPPER, &wformat, (DWORD)m_internal->m_sndWin, 0, CALLBACK_WINDOW); if (result != MMSYSERR_NOERROR) { m_snderror = wxSOUND_INVDEV; return false; } m_current_frag_in = WXSOUND_MAX_QUEUE-1; m_input_frag_in = 0; m_internal->m_input_enabled = true; } if (mode & wxSOUND_OUTPUT) { if (!AllocHeaders(wxSOUND_OUTPUT)) { CloseDevice(); return false; } } if (mode & wxSOUND_INPUT) { if (!AllocHeaders(wxSOUND_INPUT)) { CloseDevice(); return false; } } return true;}// -------------------------------------------------------------------------// CloseDevice() closes the driver handles and frees memory allocated for// IO queues.// -------------------------------------------------------------------------void wxSoundStreamWin::CloseDevice(){ if (m_internal->m_output_enabled) { FreeHeaders(wxSOUND_OUTPUT); m_internal->m_output_enabled = false; waveOutClose(m_internal->m_devout); } if (m_internal->m_input_enabled) { FreeHeaders(wxSOUND_INPUT); m_internal->m_input_enabled = false; waveInClose(m_internal->m_devin); }}// -------------------------------------------------------------------------// AllocHeader(int mode)//// mode has the same mean as in OpenDevice() except that here the two flags// must be exclusive.// AllocHeader() initializes an element of an operation (this can be input// or output). It means it allocates the sound header's memory block // and "prepares" it (It is needed by Windows). At the same time, it sets// private datas so we can the header's owner (See callback).//// It returns the new allocated block or NULL.// -------------------------------------------------------------------------wxSoundInfoHeader *wxSoundStreamWin::AllocHeader(int mode){ wxSoundInfoHeader *info; WAVEHDR *header; // Some memory allocation info = new wxSoundInfoHeader; info->m_h_data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, GetBestSize()); info->m_h_header = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR)); if (!info->m_h_data || !info->m_h_header) { delete info; m_snderror = wxSOUND_MEMERROR; return NULL; } // Get the two pointers from the system info->m_data = (char *)GlobalLock(info->m_h_data); info->m_header = (WAVEHDR *)GlobalLock(info->m_h_header); // Set the header's mode info->m_mode = mode; // Set the parent of the header info->m_driver = this; // Clean it up ClearHeader(info); header = info->m_header; // Initialize Windows variables header->lpData = info->m_data; header->dwBufferLength = GetBestSize(); header->dwUser = (DWORD)info; header->dwFlags = WHDR_DONE; // "Prepare" the header if (mode == wxSOUND_INPUT) { MMRESULT result; result = waveInPrepareHeader(m_internal->m_devin, header, sizeof(WAVEHDR)); if (result != MMSYSERR_NOERROR) { // If something goes wrong, free everything. GlobalUnlock(info->m_data); GlobalUnlock(info->m_header); GlobalFree(info->m_h_data); GlobalFree(info->m_h_header); delete info; m_snderror = wxSOUND_IOERROR; return NULL; } } else if (mode == wxSOUND_OUTPUT) { MMRESULT result; result = waveOutPrepareHeader(m_internal->m_devout, header, sizeof(WAVEHDR)); if (result != MMSYSERR_NOERROR) { // If something goes wrong, free everything. GlobalUnlock(info->m_data); GlobalUnlock(info->m_header); GlobalFree(info->m_h_data); GlobalFree(info->m_h_header); delete info; m_snderror = wxSOUND_IOERROR; return NULL; } } return info;}// -------------------------------------------------------------------------// AllocHeaders(int mode)//// "mode" has the same mean as for OpenDevice() except that the two flags must// be exclusive.// AllocHeaders() allocates WXSOUND_MAX_QUEUE (= 128) blocks for an operation// queue. It uses AllocHeader() for each element.//// Once it has allocated all blocks, it returns true and if an error occurred// it returns false.// -------------------------------------------------------------------------bool wxSoundStreamWin::AllocHeaders(int mode){ int i; wxSoundInfoHeader **headers; if (mode == wxSOUND_OUTPUT) headers = m_headers_play = new wxSoundInfoHeader *[WXSOUND_MAX_QUEUE];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -