19 #ifdef HAVE_OSS_SUPPORT 25 #include <sys/ioctl.h> 26 #include <sys/soundcard.h> 28 #include <sys/types.h> 33 #include <QLatin1Char> 35 #include <KLocalizedString> 47 #define MIN_PLAYBACK_BUFFER 8 50 #define MAX_PLAYBACK_BUFFER 16 53 #define MAX_CHANNELS 7 58 #define AFMT_S24_LE 0x00008000 61 #define AFMT_S24_BE 0x00010000 64 #define AFMT_S32_LE 0x00001000 67 #define AFMT_S32_BE 0x00002000 70 #ifndef SNDCTL_DSP_SPEED 71 #define SNDCTL_DSP_SPEED SOUND_PCM_WRITE_RATE 74 #ifndef SNDCTL_DSP_CHANNELS 75 #define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS 78 #ifndef SOUND_PCM_SETFMT 79 #define SOUND_PCM_SETFMT SOUND_PCM_WRITE_BITS 82 #ifndef SNDCTL_DSP_SETFMT 83 #define SNDCTL_DSP_SETFMT SOUND_PCM_SETFMT 112 unsigned int channels,
unsigned int bits,
113 unsigned int bufbase)
115 qDebug(
"PlayBackOSS::open(device=%s,rate=%0.1f,channels=%u," 116 "bits=%u, bufbase=%u)",
DBG(device.split(
_(
"|")).at(0)),
117 rate, channels, bits, bufbase);
138 reason = i18n(
"I/O error. Maybe the driver\n"\
139 "is not present in your kernel or it is not\n"\
140 "properly configured.");
144 "The device is busy. Maybe some other application is\n"\
145 "currently using it. Please try again later.\n"\
146 "(Hint: you might find out the name and process ID of\n"\
147 "the program by calling: \"fuser -v %1\"\n"\
148 "on the command line.)",
152 reason = QString::fromLocal8Bit(strerror(errno));
160 if (fcntl(
m_handle, F_GETFL) & O_NONBLOCK) {
162 return i18n(
"The device '%1' cannot be opened "\
163 "in the correct mode.",
169 #ifdef OSS_GETVERSION 170 ioctl(
m_handle, OSS_GETVERSION, &m_oss_version);
175 case 8: format = AFMT_U8;
break;
178 default: format = AFMT_S16_LE;
182 int oldformat = format;
184 (format != oldformat)) {
185 return i18n(
"%1 bits per sample are not supported",
m_bits);
190 (format != oldformat)) {
191 return i18n(
"%1 channels playback is not supported",
m_channels);
197 (int_rate < 0.9 *
m_rate) || (int_rate > 1.1 *
m_rate)) {
198 return i18n(
"Playback rate %1 Hz is not supported", int_rate);
207 if (ioctl(
m_handle, SNDCTL_DSP_SETFRAGMENT, &bufbase) == -1) {
208 return i18n(
"Unusable buffer size: %1", 1 << bufbase);
224 if (m_oss_version >= 0x040000) {
231 if (m_oss_version >= 0x040000) {
245 if (!
m_encoder)
return i18n(
"Out of memory");
253 return i18n(
"Out of memory");
263 qWarning(
"PlayBackOSS::write(): buffer overflow ?!");
270 unsigned int remaining = samples.
size();
271 unsigned int offset = 0;
273 unsigned int length = remaining;
280 m_buffer_used += length;
304 if (res < 0) perror(__FUNCTION__);
329 if (name.contains(
_(
"%1"))) {
334 for (
unsigned int index=0; index < 64; index++)
338 file.setFileName(name);
342 if (!list.contains(name))
350 static void scanFiles(QStringList &list,
const QString &dirname,
356 dir.setPath(dirname);
357 dir.setNameFilters(mask.split(QLatin1Char(
' ')));
358 dir.setFilter(QDir::Files | QDir::Writable | QDir::System);
359 dir.setSorting(QDir::Name);
360 files = dir.entryList();
362 for (QStringList::Iterator it=files.begin(); it != files.end(); ++it) {
363 QString devicename = dirname + QDir::separator() + (*it);
381 QStringList list, dirlist;
387 foreach (QString dir, dirlist)
389 list.append(
_(
"#EDIT#"));
390 list.append(
_(
"#SELECT#"));
400 if (filter.length()) filter +=
_(
"\n");
401 filter +=
_(
"dsp*|") + i18n(
"OSS playback device (dsp*)");
403 if (filter.length()) filter +=
_(
"\n");
404 filter +=
_(
"adsp*|") + i18n(
"ALSA playback device (adsp*)");
406 if (filter.length()) filter +=
_(
"\n");
407 filter +=
_(
"*|") + i18n(
"Any device (*)");
455 compression =
static_cast<int>(
497 if (!device.length())
return -1;
501 fd =
::open(device.toLocal8Bit(), O_WRONLY | O_NONBLOCK);
503 qWarning(
"PlayBackOSS::openDevice('%s') - failed, errno=%d (%s)",
505 errno, strerror(errno));
508 ::fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
511 #ifdef OSS_GETVERSION 517 qWarning(
"PlayBackOSS::openDevice('%s') - failed, errno=%d (%s)",
518 DBG(device), errno, strerror(errno));
527 QList<unsigned int> bits;
530 int mask = AFMT_QUERY;
537 err = ::ioctl(fd, SNDCTL_DSP_GETFMTS, &mask);
539 qWarning(
"PlayBackOSS::supportedBits() - "\
540 "SNDCTL_DSP_GETFMTS failed, "\
541 "fd=%d, result=%d, error=%d (%s)",
542 fd, err, errno, strerror(errno));
549 if (err < 0)
return bits;
553 for (
unsigned int bit=0; bit < (
sizeof(mask) << 3); bit++) {
554 if (!(mask & (1 << bit)))
continue;
563 if ((c == compression) && !(bits.contains(b))) {
573 unsigned int &min,
unsigned int &max)
581 if (fd < 0)
return -1;
587 Q_ASSERT(real_tracks == t);
593 if (t >= MAX_CHANNELS) {
595 qWarning(
"no minimum track number found, err=%d", err);
605 Q_ASSERT(real_tracks == t);
static void scanFiles(QStringList &list, const QString &dirname, const QString &mask)
virtual unsigned int rawBytesPerSample()=0
#define SNDCTL_DSP_SETFMT
virtual QString fileFilter() Q_DECL_OVERRIDE
unsigned int m_buffer_size
virtual int detectChannels(const QString &device, unsigned int &min, unsigned int &max) Q_DECL_OVERRIDE
virtual int write(const Kwave::SampleArray &samples) Q_DECL_OVERRIDE
#define MIN_PLAYBACK_BUFFER
Kwave::SampleArray m_buffer
static void scanDirectory(QStringList &list, const QString &dir)
int openDevice(const QString &device)
virtual ~PlayBackOSS() Q_DECL_OVERRIDE
virtual QStringList supportedDevices() Q_DECL_OVERRIDE
unsigned int size() const
#define MAX_PLAYBACK_BUFFER
static bool addIfExists(QStringList &list, const QString &name)
virtual int close() Q_DECL_OVERRIDE
virtual QList< unsigned int > supportedBits(const QString &device) Q_DECL_OVERRIDE
unsigned int m_buffer_used
virtual void encode(const Kwave::SampleArray &samples, unsigned int count, QByteArray &raw_data)=0
bool resize(unsigned int size) Q_REQUIRED_RESULT
Kwave::SampleEncoder * m_encoder
void format2mode(int format, int &compression, int &bits, Kwave::SampleFormat::Format &sample_format) const
#define SNDCTL_DSP_CHANNELS
virtual QString open(const QString &device, double rate, unsigned int channels, unsigned int bits, unsigned int bufbase) Q_DECL_OVERRIDE