/* * vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab * * $LastChangedDate$ * $Revision$ * $LastChangedBy$ * $URL$ * * Copyright 2009-2011 Eric Connell * Copyright 2010-2011 Roman Tetelman * * This file is part of Mangler. * * Mangler 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 3 of the License, or * (at your option) any later version. * * Mangler 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 Mangler. If not, see . */ #include "mangler.h" #ifdef HAVE_OSS #include "mangleraudio.h" #include "mangleross.h" ManglerOSS::ManglerOSS(uint32_t rate, uint8_t channels, uint32_t pcm_framesize) {/*{{{*/ oss_fd = -1; this->pcm_framesize = pcm_framesize; }/*}}}*/ ManglerOSS::~ManglerOSS() {/*{{{*/ if (oss_fd >= 0) { close(); } }/*}}}*/ bool ManglerOSS::open(int type, Glib::ustring device, int rate, int channels) {/*{{{*/ if ((oss_fd = ::open((device == "") ? "/dev/dsp" : device.c_str(), (type >= AUDIO_OUTPUT) ? O_WRONLY : O_RDONLY)) < 0) { fprintf(stderr, "oss: open() %s failed: %s\n", (device == "") ? "/dev/dsp" : device.c_str(), strerror(errno)); return false; } int opt; opt = AFMT_S16_NE; if ((::ioctl(oss_fd, SNDCTL_DSP_SETFMT, &opt) < 0) || opt != AFMT_S16_NE) { fprintf(stderr, "oss: ioctl() SNDCTL_DSP_SETFMT failed: %s\n", strerror(errno)); close(); return false; } opt = channels; if ((::ioctl(oss_fd, SNDCTL_DSP_CHANNELS, &opt) < 0) || opt != (int)channels) { fprintf(stderr, "oss: ioctl() SNDCTL_DSP_CHANNELS failed: %s\n", strerror(errno)); close(); return false; } opt = rate; if ((::ioctl(oss_fd, SNDCTL_DSP_SPEED, &opt) < 0) || opt != (int)rate) { fprintf(stderr, "oss: ioctl() SNDCTL_DSP_SPEED failed: %s\n", strerror(errno)); close(); return false; } return true; }/*}}}*/ void ManglerOSS::close(bool drain) {/*{{{*/ if (oss_fd >= 0) { ::close(oss_fd); oss_fd = -1; } }/*}}}*/ bool ManglerOSS::write(uint8_t *sample, uint32_t length, int channels) {/*{{{*/ if (oss_fd < 0) { return false; } if (::write(oss_fd, sample, length) < 0) { fprintf(stderr, "oss: write() failed: %s\n", strerror(errno)); return false; } return true; }/*}}}*/ bool ManglerOSS::read(uint8_t *buf) {/*{{{*/ if (oss_fd < 0) { return false; } if (::read(oss_fd, buf, pcm_framesize) < 0) { fprintf(stderr, "oss: read() failed: %s\n", strerror(errno)); return false; } return true; }/*}}}*/ Glib::ustring ManglerOSS::getAudioSubsystem(void) {/*{{{*/ return Glib::ustring("oss"); }/*}}}*/ void ManglerOSS::getDeviceList(std::vector& inputDevices, std::vector& outputDevices) {/*{{{*/ int idx_p = 0, idx_c = 0; #if SOUND_VERSION >= 0x040000 bool ossv3 = false; int fd, dev, version = 0; oss_sysinfo sysinfo; oss_audioinfo ainfo; if ((fd = ::open("/dev/mixer", O_RDONLY)) < 0) { fprintf(stderr, "oss: open() /dev/mixer failed: %s\n", strerror(errno)); ossv3 = true; } if (!ossv3 && (::ioctl(fd, OSS_GETVERSION, &version) < 0 || version < 0x040000)) { fprintf(stderr, "oss: ioctl() failed: version too old for device enumeration\n"); ::close(fd); ossv3 = true; } if (!ossv3 && ::ioctl(fd, SNDCTL_SYSINFO, &sysinfo) < 0) { fprintf(stderr, "oss: ioctl() failed: %s\n", strerror(errno)); ::close(fd); ossv3 = true; } if (!ossv3) { if (!sysinfo.numaudios) { fprintf(stderr, "oss: no sound cards found!\n"); ::close(fd); return; } for (dev = 0; dev < sysinfo.numaudios; dev++) { ainfo.dev = dev; if (::ioctl(fd, SNDCTL_AUDIOINFO, &ainfo) < 0 || !ainfo.enabled) { continue; } if (ainfo.caps & PCM_CAP_OUTPUT) { outputDevices.push_back( new ManglerAudioDevice( idx_p++, ainfo.devnode, ainfo.name) ); } if (ainfo.caps & PCM_CAP_INPUT) { inputDevices.push_back( new ManglerAudioDevice( idx_c++, ainfo.devnode, ainfo.name) ); } } ::close(fd); return; } fprintf(stderr, "oss: falling back to ossv3 device listing\n"); #endif Glib::PatternSpec dsp("dsp*"); Glib::Dir dir("/dev"); Glib::ustring path; for (Glib::DirIterator iter = dir.begin(); iter != dir.end(); iter++) { if (dsp.match(*iter)) { path = "/dev/" + *iter; outputDevices.push_back( new ManglerAudioDevice( idx_p++, path, path) ); inputDevices.push_back( new ManglerAudioDevice( idx_c++, path, path) ); } } }/*}}}*/ #endif