19 #ifdef HAVE_OSS_SUPPORT 24 #include <sys/ioctl.h> 25 #include <sys/soundcard.h> 27 #include <sys/types.h> 32 #include <QLatin1Char> 45 #define AFMT_S24_LE 0x00008000 48 #define AFMT_S24_BE 0x00010000 51 #define AFMT_S32_LE 0x00001000 54 #define AFMT_S32_BE 0x00002000 57 #ifndef SNDCTL_DSP_SPEED 58 #define SNDCTL_DSP_SPEED SOUND_PCM_WRITE_RATE 61 #ifndef SNDCTL_DSP_CHANNELS 62 #define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS 65 #ifndef SOUND_PCM_SETFMT 66 #define SOUND_PCM_SETFMT SOUND_PCM_WRITE_BITS 69 #ifndef SNDCTL_DSP_SETFMT 70 #define SNDCTL_DSP_SETFMT SOUND_PCM_SETFMT 74 #define MAX_CHANNELS 2 76 //*************************************************************************** 79 m_fd(-1), m_rate(0), m_tracks(0), m_oss_version(-1)
94 if (!dev.length())
return QString::number(EINVAL);
97 int fd =
::open(dev.toLocal8Bit(), O_RDONLY | O_NONBLOCK);
99 qWarning(
"open failed, fd=%d, errno=%d (%s)",
100 fd, errno, strerror(errno));
108 reason = QString::number(ENODEV);
111 reason = QString::number(EBUSY);
114 reason = QString::fromLocal8Bit(strerror(errno));
122 #ifdef OSS_GETVERSION 136 unsigned int length = buffer.size();
140 Q_ASSERT(buffer.size());
142 Q_ASSERT(offset < length);
143 if (
m_fd < 0)
return -EBADF;
144 if (buffer.isEmpty())
return -EINVAL;
145 if (!length)
return -EINVAL;
146 if (offset >= length)
return -EINVAL;
151 int blocksize = length;
152 int err = ioctl(
m_fd, SNDCTL_DSP_GETBLKSIZE, &blocksize);
154 qDebug(
"blocksize = %u", blocksize);
159 blocksize = (127 << 16) + 6;
160 err = ioctl(
m_fd, SNDCTL_DSP_SETFRAGMENT, &blocksize);
165 if (rate < 1) rate = 1;
167 unsigned int timeout = (length / rate) * 2;
168 if (timeout < 2) timeout = 2;
169 quint8 *buf =
reinterpret_cast<quint8 *
>(buffer.data()) + offset;
172 retval = ioctl(
m_fd, SNDCTL_DSP_SETTRIGGER, &mask);
174 mask = PCM_ENABLE_INPUT;
175 retval = ioctl(
m_fd, SNDCTL_DSP_SETTRIGGER, &mask);
184 retval = select(
m_fd+1, &rfds, Q_NULLPTR, Q_NULLPTR, &tv);
190 qWarning(
"RecordOSS::read() - select() failed errno=%d (%s)",
191 errno, strerror(errno));
196 if ((res == -1) && (errno == EINTR))
199 if ((res == -1) && (errno == EAGAIN))
203 qWarning(
"RecordOSS::read() - read error %d (%s)",
204 errno, strerror(errno));
211 printf(
"No data within 5 seconds.\n");
222 if (
m_fd < 0)
return 0;
235 if (name.contains(
_(
"%1"))) {
240 for (
unsigned int index=0; index < 64; index++)
244 file.setFileName(name);
248 if (!list.contains(name))
256 static void scanFiles(QStringList &list,
const QString &dirname,
262 dir.setPath(dirname);
263 dir.setNameFilters(mask.split(QLatin1Char(
' ')));
264 dir.setFilter(QDir::Files | QDir::Readable | QDir::System);
265 dir.setSorting(QDir::Name);
266 files = dir.entryList();
268 for (QStringList::Iterator it = files.begin(); it != files.end(); ++it) {
269 QString devicename = dirname + QDir::separator() + (*it);
287 QStringList list, dirlist;
292 foreach(QString dir, dirlist)
294 list.append(
_(
"#EDIT#"));
295 list.append(
_(
"#SELECT#"));
305 if (filter.length()) filter +=
_(
"\n");
306 filter +=
_(
"audio*|") + i18n(
"OSS recording device (audio*)");
307 filter +=
_(
"dsp*|") + i18n(
"OSS recording device (dsp*)");
309 if (filter.length()) filter +=
_(
"\n");
310 filter +=
_(
"adsp*|") + i18n(
"ALSA recording device (adsp*)");
312 if (filter.length()) filter +=
_(
"\n");
313 filter +=
_(
"*|") + i18n(
"Any device (*)");
338 if (t >= MAX_CHANNELS) {
340 qWarning(
"no minimum track number found, err=%d", err);
348 for (t = MAX_CHANNELS; t >= min; t--) {
358 qDebug(
"RecordOSS::detectTracks, min=%u, max=%u", min, max);
360 return (max > 0) ? 0 : -1;
371 if (err < 0)
return err;
392 static const int known_rates[] = {
433 for (
unsigned int i=0; i <
sizeof(known_rates)/
sizeof(
int); i++) {
434 int rate = known_rates[i];
443 bool is_duplicate =
false;
444 foreach (
const double &r, list)
445 if (qFuzzyCompare(rate, r)) { is_duplicate =
true;
break; }
446 if (is_duplicate)
continue;
465 if (err < 0)
return err;
469 new_rate =
static_cast<double>(rate);
579 int err = ioctl(
m_fd, SNDCTL_DSP_GETFMTS, &mask);
580 if (err < 0)
return bits;
585 mask &= (AFMT_U16_LE | AFMT_U16_BE);
586 if (mask != (AFMT_U16_LE | AFMT_U16_BE))
return mask;
587 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 596 mask &= (AFMT_S16_LE | AFMT_S16_BE);
597 if (mask != (AFMT_S16_LE | AFMT_S16_BE))
return mask;
598 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 608 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 618 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 625 qWarning(
"RecordOSS: unknown format: sample_format=%d, bits=%d",
626 static_cast<int>(sample_format), bits);
634 QList<Kwave::Compression::Type> compressions;
636 int mask = AFMT_QUERY;
638 err = ioctl(
m_fd, SNDCTL_DSP_GETFMTS, &mask);
639 if (err < 0)
return compressions;
645 if (mask & (AFMT_U16_LE | AFMT_U16_BE | AFMT_S16_LE | AFMT_S16_BE |
658 int bits, format = AFMT_QUERY;
663 if (err < 0)
return -1;
664 format2mode(format, compression, bits, sample_format);
667 compression = new_compression;
670 format =
mode2format(compression, bits, sample_format);
672 if (err < 0)
return -1;
681 int mask = AFMT_QUERY;
696 QList<unsigned int> bits;
699 int mask = AFMT_QUERY;
701 err = ioctl(
m_fd, SNDCTL_DSP_GETFMTS, &mask);
702 if (err < 0)
return bits;
706 for (
unsigned int bit=0; bit < (
sizeof(mask) << 3); bit++) {
707 if (!(mask & (1 << bit)))
continue;
717 if ((c == compression) && !(bits.contains(b))) {
724 qDebug(
"RecordOSS: your device supports AC3 which is not "\
725 "yet supported, sorry :-(");
735 int bits, format = AFMT_QUERY;
740 if (err < 0)
return err;
741 format2mode(format, compression, bits, sample_format);
747 int oldformat = format;
748 format =
mode2format(compression, bits, sample_format);
750 if (err < 0)
return err;
751 if (oldformat != format)
return -1;
760 int mask = AFMT_QUERY;
762 if (err < 0)
return err;
775 QList<Kwave::SampleFormat::Format> formats;
778 int mask = AFMT_QUERY;
780 err = ioctl(
m_fd, SNDCTL_DSP_GETFMTS, &mask);
781 if (err < 0)
return formats;
787 for (
unsigned int bit = 0; bit < (
sizeof(mask) << 3); bit++) {
788 if (!(mask & (1 << bit)))
continue;
797 if ((c == compression) && (b == bits_per_sample)) {
799 if (!formats.contains(s)) formats += s;
811 int bits, format = AFMT_QUERY;
816 if (err < 0)
return err;
817 format2mode(format, compression, bits, sample_format);
820 sample_format = new_format;
823 int oldformat = format;
824 format =
mode2format(compression, bits, sample_format);
826 if (err < 0)
return err;
827 if (oldformat != format)
return -1;
836 int mask = AFMT_QUERY;
851 int mask = AFMT_QUERY;
861 if (mask & (AFMT_S8 | AFMT_U8))
virtual QList< unsigned int > supportedBits() Q_DECL_OVERRIDE
virtual int read(QByteArray &buffer, unsigned int offset) Q_DECL_OVERRIDE
virtual QString open(const QString &dev) Q_DECL_OVERRIDE
#define SNDCTL_DSP_SETFMT
virtual QList< Kwave::Compression::Type > detectCompressions() Q_DECL_OVERRIDE
virtual double sampleRate() Q_DECL_OVERRIDE
virtual Kwave::Compression::Type compression() Q_DECL_OVERRIDE
virtual Kwave::byte_order_t endianness() Q_DECL_OVERRIDE
virtual QStringList supportedDevices() Q_DECL_OVERRIDE
static void scanDirectory(QStringList &list, const QString &dir)
virtual QList< double > detectSampleRates() Q_DECL_OVERRIDE
void format2mode(int format, Kwave::Compression::Type &compression, int &bits, Kwave::SampleFormat::Format &sample_format)
int mode2format(Kwave::Compression::Type compression, int bits, Kwave::SampleFormat::Format sample_format)
virtual Kwave::SampleFormat::Format sampleFormat() Q_DECL_OVERRIDE
virtual int setSampleFormat(Kwave::SampleFormat::Format new_format) Q_DECL_OVERRIDE
static void scanFiles(QStringList &list, const QString &dirname, const QString &mask)
virtual int bitsPerSample() Q_DECL_OVERRIDE
virtual int close() Q_DECL_OVERRIDE
static bool addIfExists(QStringList &list, const QString &name)
virtual int setSampleRate(double &new_rate) Q_DECL_OVERRIDE
virtual QString fileFilter() Q_DECL_OVERRIDE
virtual ~RecordOSS() Q_DECL_OVERRIDE
virtual int setCompression(Kwave::Compression::Type new_compression) Q_DECL_OVERRIDE
virtual int tracks() Q_DECL_OVERRIDE
virtual int detectTracks(unsigned int &min, unsigned int &max) Q_DECL_OVERRIDE
#define SNDCTL_DSP_CHANNELS
virtual QList< Kwave::SampleFormat::Format > detectSampleFormats() Q_DECL_OVERRIDE
virtual int setBitsPerSample(unsigned int new_bits) Q_DECL_OVERRIDE
virtual int setTracks(unsigned int &tracks) Q_DECL_OVERRIDE