📄 sndwin.cpp
字号:
else headers = m_headers_rec = new wxSoundInfoHeader *[WXSOUND_MAX_QUEUE]; memset(headers, 0, WXSOUND_MAX_QUEUE*sizeof(wxSoundInfoHeader *)); for (i=0;i<WXSOUND_MAX_QUEUE;i++) { headers[i] = AllocHeader(mode); if (!headers[i]) { FreeHeaders(mode); return false; } } return true;}// -------------------------------------------------------------------------// FreeHeader(int mode)//// "mode" has the same mean as for OpenDevice() except that the two flags must// be exclusive.// FreeHeader() frees a memory block and "unprepares" it.// -------------------------------------------------------------------------void wxSoundStreamWin::FreeHeader(wxSoundInfoHeader *header, int mode){ if (mode == wxSOUND_OUTPUT) waveOutUnprepareHeader(m_internal->m_devout, header->m_header, sizeof(WAVEHDR)); else waveInUnprepareHeader(m_internal->m_devin, header->m_header, sizeof(WAVEHDR)); GlobalUnlock(header->m_data); GlobalUnlock(header->m_header); GlobalFree(header->m_h_header); GlobalFree(header->m_h_data); delete header;}// -------------------------------------------------------------------------// FreeHeaders(int mode)//// "mode" has the same mean as for OpenDevice() except that the two flags must// be exclusive.// FreeHeaders() frees all an operation queue once it has checked that// all buffers have been terminated.// -------------------------------------------------------------------------void wxSoundStreamWin::FreeHeaders(int mode){ int i; wxSoundInfoHeader ***headers; if (mode == wxSOUND_OUTPUT) headers = &m_headers_play; else headers = &m_headers_rec; for (i=0;i<WXSOUND_MAX_QUEUE;i++) { if ((*headers)[i]) { // We wait for the end of the buffer WaitFor((*headers)[i]); // Then, we free the header FreeHeader((*headers)[i], mode); } } delete[] (*headers); (*headers) = NULL;}// -------------------------------------------------------------------------// WaitFor(wxSoundInfoHeader *info)//// "info" is one element of an IO queue// WaitFor() checks whether the specified block has been terminated.// If it hasn't been terminated, it waits for its termination.//// NB: if it's a partially filled buffer it adds it to the Windows queue// -------------------------------------------------------------------------void wxSoundStreamWin::WaitFor(wxSoundInfoHeader *info){ // If the buffer is finished, we return immediately if (!info->m_playing) { // We begun filling it: we must send it to the Windows queue if (info->m_position != 0) { memset(info->m_data + info->m_position, 0, info->m_size); AddToQueue(info); } } if (m_waiting_for) { // PROBLEM // return; } m_waiting_for = true; // Else, we wait for its termination while (info->m_playing || info->m_recording) wxYield(); m_waiting_for = false;}// -------------------------------------------------------------------------// AddToQueue(wxSoundInfoHeader *info)//// For "info", see WaitFor()// AddToQueue() sends the IO queue element to the Windows queue.//// Warning: in the current implementation, it partially assume we send the// element in the right order. This is true in that implementation but if// you use it elsewhere, be careful: it may shuffle all your sound datas.// -------------------------------------------------------------------------bool wxSoundStreamWin::AddToQueue(wxSoundInfoHeader *info){ MMRESULT result; if (info->m_mode == wxSOUND_INPUT) { // Increment the input fragment pointer result = waveInAddBuffer(m_internal->m_devin, info->m_header, sizeof(WAVEHDR)); if (result == MMSYSERR_NOERROR) info->m_recording = true; else return false; } else if (info->m_mode == wxSOUND_OUTPUT) { result = waveOutWrite(m_internal->m_devout, info->m_header, sizeof(WAVEHDR)); if (result == MMSYSERR_NOERROR) info->m_playing = true; else return false; } return true;}// -------------------------------------------------------------------------// ClearHeader(wxSoundInfoHeader *info)//// ClearHeader() reinitializes the parameters of "info" to their default// value.// -------------------------------------------------------------------------void wxSoundStreamWin::ClearHeader(wxSoundInfoHeader *info){ info->m_playing = false; info->m_recording = false; info->m_position = 0; info->m_size = GetBestSize();}// -------------------------------------------------------------------------// wxSoundInfoHeader *NextFragmentOutput()//// NextFragmentOutput() looks for a free output block. It will always// return you a non-NULL pointer but it may waits for an empty buffer a long// time.// -------------------------------------------------------------------------wxSoundInfoHeader *wxSoundStreamWin::NextFragmentOutput(){ if (m_headers_play[m_current_frag_out]->m_playing) { m_current_frag_out = (m_current_frag_out + 1) % WXSOUND_MAX_QUEUE; if (m_headers_play[m_current_frag_out]->m_playing) WaitFor(m_headers_play[m_current_frag_out]); } if (m_current_frag_out == m_output_frag_out) m_queue_filled = true; return m_headers_play[m_current_frag_out];}// -------------------------------------------------------------------------// The behaviour of Write is documented in the global documentation.// -------------------------------------------------------------------------wxSoundStream& wxSoundStreamWin::Write(const void *buffer, wxUint32 len){ m_lastcount = 0; if (!m_internal->m_output_enabled) { m_snderror = wxSOUND_NOTSTARTED; return *this; } while (len > 0) { wxSoundInfoHeader *header; wxUint32 to_copy; // Get a new output fragment header = NextFragmentOutput(); to_copy = (len > header->m_size) ? header->m_size : len; memcpy(header->m_data + header->m_position, buffer, to_copy); header->m_position += to_copy; header->m_size -= to_copy; buffer = (((const char *)buffer) + to_copy); len -= to_copy; m_lastcount += to_copy; // If the fragment is full, we send it to the Windows queue. if (header->m_size == 0) if (!AddToQueue(header)) { m_snderror = wxSOUND_IOERROR; return *this; } } return *this;}// -------------------------------------------------------------------------// NextFragmentInput is not functional.// -------------------------------------------------------------------------wxSoundInfoHeader *wxSoundStreamWin::NextFragmentInput(){ wxSoundInfoHeader *header; // Queue pointer: reader m_current_frag_in = (m_current_frag_in + 1) % WXSOUND_MAX_QUEUE; header = m_headers_rec[m_current_frag_in]; // If the current buffer is in recording mode, we must wait for its // completion. if (header->m_recording) WaitFor(header); // We reached the writer position: the queue is full. if (m_current_frag_in == m_input_frag_in) m_queue_filled = true; return header;}// -------------------------------------------------------------------------// The behaviour of Read is documented in the global documentation.// -------------------------------------------------------------------------wxSoundStream& wxSoundStreamWin::Read(void *buffer, wxUint32 len){ wxSoundInfoHeader *header; wxUint32 to_copy; m_lastcount = 0; if (!m_internal->m_input_enabled) return *this; while (len > 0) { header = NextFragmentInput(); to_copy = (len > header->m_size) ? header->m_size : len; memcpy(buffer, header->m_data + header->m_position, to_copy); header->m_position += to_copy; header->m_size -= to_copy; buffer = (((char *)buffer) + to_copy); len -= to_copy; m_lastcount += to_copy; if (header->m_size == 0) { ClearHeader(header); if (!AddToQueue(header)) { m_snderror = wxSOUND_IOERROR; return *this; } } } return *this;}// -------------------------------------------------------------------------// NotifyDoneBuffer(wxUint32 dev_handle)//// NotifyDoneBuffer() is called by wxSoundHandlerProc each time a sound// fragment finished. It reinitializes the parameters of the fragment and// sends an event to the clients.// -------------------------------------------------------------------------void wxSoundStreamWin::NotifyDoneBuffer(wxUint32 WXUNUSED(dev_handle), int flag){ wxSoundInfoHeader *info; if (flag == wxSOUND_OUTPUT) { if (!m_internal->m_output_enabled) return; // Queue pointer: reader m_output_frag_out = (m_output_frag_out + 1) % WXSOUND_MAX_QUEUE; info = m_headers_play[m_output_frag_out]; // Clear header to tell the system the buffer is free now ClearHeader(info); m_queue_filled = false; if (!m_waiting_for) // Try to requeue a new buffer. OnSoundEvent(wxSOUND_OUTPUT); } else { if (!m_internal->m_input_enabled) return; // Recording completed m_headers_rec[m_input_frag_in]->m_recording = false; // Queue pointer: writer m_input_frag_in = (m_input_frag_in + 1) % WXSOUND_MAX_QUEUE; if (!m_waiting_for) OnSoundEvent(wxSOUND_INPUT); m_queue_filled = false; }}// -------------------------------------------------------------------------// SetSoundFormat()// -------------------------------------------------------------------------bool wxSoundStreamWin::SetSoundFormat(const wxSoundFormatBase& base){ // TODO: detect best format return wxSoundStream::SetSoundFormat(base);}// -------------------------------------------------------------------------// StartProduction()// -------------------------------------------------------------------------bool wxSoundStreamWin::StartProduction(int evt){ if (!m_internal) return false; if ((m_internal->m_output_enabled && (evt & wxSOUND_OUTPUT)) || (m_internal->m_input_enabled && (evt & wxSOUND_INPUT))) CloseDevice(); if (!OpenDevice(evt)) return false; m_production_started = true; m_queue_filled = false; // Send a dummy event to start. if (evt & wxSOUND_OUTPUT) OnSoundEvent(wxSOUND_OUTPUT); if (evt & wxSOUND_INPUT) { int i; for (i=0;i<WXSOUND_MAX_QUEUE;i++) AddToQueue(m_headers_rec[i]); waveInStart(m_internal->m_devin); } return true;}// -------------------------------------------------------------------------// StopProduction()// ------------------------------------------------------------------------bool wxSoundStreamWin::StopProduction(){ if (!m_production_started) { m_snderror = wxSOUND_NOTSTARTED; return false; } m_snderror = wxSOUND_NOERROR; m_production_started = false; CloseDevice(); return true;}// -------------------------------------------------------------------------// QueueFilled()// -------------------------------------------------------------------------bool wxSoundStreamWin::QueueFilled() const{ return (!m_production_started || m_queue_filled);}// --------------------------------------------------------------------------// wxSoundWinModule// --------------------------------------------------------------------------class wxSoundWinModule : public wxModule { DECLARE_DYNAMIC_CLASS(wxSoundWinModule) public: bool OnInit(); void OnExit();};IMPLEMENT_DYNAMIC_CLASS(wxSoundWinModule, wxModule)bool wxSoundWinModule::OnInit() { wxSoundHandleList = new wxList(wxKEY_INTEGER); return true;}void wxSoundWinModule::OnExit() { delete wxSoundHandleList;}#endif // __WINDOWS__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -