📄 osssoundcard.cc
字号:
//// Copyright (c) 2004 by Istv醤 V醨adi//// This file is part of dxr3Player, a DVD player written specifically // for the DXR3 (aka Hollywood+) decoder card.// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//------------------------------------------------------------------------------#include "OSSSoundcard.h"#include "util/Log.h"#include <cassert>#include <linux/soundcard.h>//------------------------------------------------------------------------------using output::OSSSoundcard;//------------------------------------------------------------------------------//------------------------------------------------------------------------------OSSSoundcard::OSSSoundcard(const char* dsp) : Thread("output::OSSSoundcard"), bytesWritten(0), data(0), dataLength(0){ fd = POSIX::open(dsp, O_RDWR, "Cannot open DSP device"); int caps; ioctl(SNDCTL_DSP_GETCAPS, &caps, "Cannot query capabilities from the sound card!"); realTime = (caps&DSP_CAP_REALTIME)==DSP_CAP_REALTIME; triggerable = (caps&DSP_CAP_TRIGGER)==DSP_CAP_TRIGGER; audio_buf_info abi; ioctl(SNDCTL_DSP_GETOSPACE, &abi, "Cannot query output buffer info from the sound card!"); bufferSize = abi.fragstotal; bufferSize *= abi.fragsize; Log::debug("output::OSSSoundcard::OSSSoundcard: %sreal-time capable, %striggerable, buffer size: %u\n", realTime ? "" : "not ", triggerable ? "" : "not ", bufferSize); if (!realTime) { Log::debug("output::OSSSoundcard::OSSSoundcard: without real-time capability, audio and video may go out of sync!\n"); } setup(audioMode, sampleRate, stereo); stopPlayback(); start();}//------------------------------------------------------------------------------OSSSoundcard::~OSSSoundcard(){}//------------------------------------------------------------------------------void OSSSoundcard::startPlayback(){ assert(triggerable); int trigger; ioctl(SNDCTL_DSP_GETTRIGGER, &trigger, "Error querying the trigger"); trigger |= PCM_ENABLE_OUTPUT; ioctl(SNDCTL_DSP_SETTRIGGER, &trigger, "Error setting the trigger");}//------------------------------------------------------------------------------size_t OSSSoundcard::play(const void* buf, size_t count, bool /*interruptible*/){ assert(data==0); data = buf; dataLength = count; trigger(); assert(data==0); bytesWritten += dataLength; return dataLength;}//------------------------------------------------------------------------------unsigned long long OSSSoundcard::getNumberOfSamplesPlayed(){ assert(realTime); count_info info; ioctl(SNDCTL_DSP_GETOPTR, &info, "Error querying the number of samples played"); int delay; ioctl(SNDCTL_DSP_GETODELAY, &delay, "Error querying the output delay"); assert(delay>=0); // Due to bugs/inaccuracies in drivers, we need to do some tricks. // This is the maximum position, the samples played cannot be // bigger than this. ('delay' seems to be a lower bound on the real // delay...) unsigned long long maxPosition = bytesWritten - delay; // The current position may be some number of full buffers // plus the DMA pointer. The 'bytes' member of 'info' is not // always correct, at least for ALSA OSS emulation. And it would // overflow anyway after about 3 hours. unsigned long long position = (bytesWritten / bufferSize) * bufferSize; position += info.ptr; // The position may not be bigger than the maximal one, but // the difference may only be one or more bufferful. while(position>maxPosition && position>=bufferSize) position -= bufferSize; return position/getSampleSize();}//------------------------------------------------------------------------------unsigned long long OSSSoundcard::getNumberOfSamplesBuffered(){ assert(realTime); int delay; ioctl(SNDCTL_DSP_GETODELAY, &delay, "Error querying the output delay"); assert(delay>=0); return delay/getSampleSize();}//------------------------------------------------------------------------------void OSSSoundcard::stopPlayback(){ ioctl(SNDCTL_DSP_RESET, 0, "Error resetting DSP device"); bytesWritten = 0; if (triggerable) { int trigger; ioctl(SNDCTL_DSP_GETTRIGGER, &trigger, "Error querying the trigger"); trigger &= ~PCM_ENABLE_OUTPUT; ioctl(SNDCTL_DSP_SETTRIGGER, &trigger, "Error setting the trigger"); }}//------------------------------------------------------------------------------void OSSSoundcard::stop(){ Thread::stop();}//------------------------------------------------------------------------------void OSSSoundcard::doSetup(audioMode_t& mode, unsigned& rate, bool& s){ int dspFormat = (mode==AM_DIGITAL_AC3) ? AFMT_AC3 : AFMT_S16_LE; int dspSpeed = (int)rate; int dspStereo = s ? 1 : 0; ioctl(SNDCTL_DSP_SPEED, &dspSpeed, "Error setting audio sample rate to %d", dspSpeed); ioctl(SNDCTL_DSP_STEREO, &dspStereo, "Error setting DSP stereo to %d", dspStereo); ioctl(SNDCTL_DSP_SETFMT, &dspFormat, "Error setting audio format to %d", dspFormat);}//------------------------------------------------------------------------------void OSSSoundcard::perform(){ assert(data!=0); size_t written = write(data, dataLength); if (written!=dataLength) { Log::debug("output::sdl::SoundThread: written=%u, dataLength=%u\n", written, dataLength); } data = 0; dataLength = written; }//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -