fd_class_t class;
int oflags;
void *mmap_area;
+ int poll_fds;
} fd_t;
static void initialize(void);
static int poll_fds_add = 0;
static fd_t **fds;
+static inline int is_oss_device(int fd)
+{
+ return fd >= 0 && fd < open_max && fds[fd];
+}
+
static int is_dsp_device(const char *pathname)
{
if(!pathname) return 0;
static ops_t ops[FD_CLASSES] = {
[FD_OSS_DSP] = {
- close: lib_oss_pcm_close,
- write: lib_oss_pcm_write,
- read: lib_oss_pcm_read,
- ioctl: lib_oss_pcm_ioctl,
- fcntl: oss_pcm_fcntl,
- mmap: lib_oss_pcm_mmap,
- munmap: lib_oss_pcm_munmap,
+ .close = lib_oss_pcm_close,
+ .write = lib_oss_pcm_write,
+ .read = lib_oss_pcm_read,
+ .ioctl = lib_oss_pcm_ioctl,
+ .fcntl = oss_pcm_fcntl,
+ .mmap = lib_oss_pcm_mmap,
+ .munmap = lib_oss_pcm_munmap,
},
[FD_OSS_MIXER] = {
- close: lib_oss_mixer_close,
- write: bad_write,
- read: bad_read,
- ioctl: lib_oss_mixer_ioctl,
- fcntl: oss_mixer_fcntl,
- mmap: bad_mmap,
- munmap: bad_munmap,
+ .close = lib_oss_mixer_close,
+ .write = bad_write,
+ .read = bad_read,
+ .ioctl = lib_oss_mixer_ioctl,
+ .fcntl = oss_mixer_fcntl,
+ .mmap = bad_mmap,
+ .munmap = bad_munmap,
},
};
if (is_dsp_device(file)) {
fd = lib_oss_pcm_open(file, oflag);
if (fd >= 0) {
+ int nfds;
fds[fd] = calloc(sizeof(fd_t), 1);
if (fds[fd] == NULL) {
ops[FD_OSS_DSP].close(fd);
}
fds[fd]->class = FD_OSS_DSP;
fds[fd]->oflags = oflag;
- poll_fds_add += lib_oss_pcm_poll_fds(fd);
+ nfds = lib_oss_pcm_poll_fds(fd);
+ if (nfds > 0) {
+ fds[fd]->poll_fds = nfds;
+ poll_fds_add += nfds;
+ }
}
} else if (is_mixer_device(file)) {
fd = lib_oss_mixer_open(file, oflag);
if (!initialized)
initialize();
- if (fd < 0 || fd >= open_max || fds[fd] == NULL) {
+ if (! is_oss_device(fd)) {
return _close(fd);
} else {
fd_t *xfd = fds[fd];
int err;
fds[fd] = NULL;
- poll_fds_add -= lib_oss_pcm_poll_fds(fd);
+ poll_fds_add -= xfd->poll_fds;
+ if (poll_fds_add < 0) {
+ fprintf(stderr, "alsa-oss: poll_fds_add screwed up!\n");
+ poll_fds_add = 0;
+ }
err = ops[xfd->class].close(fd);
- assert(err >= 0);
+ // assert(err >= 0);
return err;
}
}
if (!initialized)
initialize();
- if (fd < 0 || fd >= open_max || fds[fd] == NULL)
+ if (! is_oss_device(fd))
return _write(fd, buf, n);
else
return ops[fds[fd]->class].write(fd, buf, n);
if (!initialized)
initialize();
- if (fd < 0 || fd >= open_max || fds[fd] == NULL)
+ if (! is_oss_device(fd))
return _read(fd, buf, n);
else
return ops[fds[fd]->class].read(fd, buf, n);
va_start(args, request);
arg = va_arg(args, void *);
va_end(args);
- if (fd < 0 || fd >= open_max || fds[fd] == NULL)
+ if (! is_oss_device(fd))
return _ioctl(fd, request, arg);
else
return ops[fds[fd]->class].ioctl(fd, request, arg);
va_start(args, cmd);
arg = va_arg(args, void *);
va_end(args);
- if (fd < 0 || fd >= open_max || fds[fd] == NULL)
+ if (! is_oss_device(fd))
return _fcntl(fd, cmd, arg);
else
return ops[fds[fd]->class].fcntl(fd, cmd, arg);
if (!initialized)
initialize();
- if (fd < 0 || fd >= open_max || fds[fd] == NULL)
+ if (! is_oss_device(fd))
return _mmap(addr, len, prot, flags, fd, offset);
result = ops[fds[fd]->class].mmap(addr, len, prot, flags, fd, offset);
if (result != NULL && result != MAP_FAILED)
}
#endif
+static int poll_with_pcm(struct pollfd *pfds, unsigned long nfds, int timeout);
+
int poll(struct pollfd *pfds, unsigned long nfds, int timeout)
{
unsigned int k;
- unsigned int nfds1;
- int count, count1;
- int direct = 1;
- struct pollfd pfds1[nfds + poll_fds_add + 16];
if (!initialized)
initialize();
+ for (k = 0; k < nfds; ++k) {
+ int fd = pfds[k].fd;
+ if (! is_oss_device(fd))
+ continue;
+ if (fds[fd]->class == FD_OSS_DSP)
+ return poll_with_pcm(pfds, nfds, timeout);
+ }
+ return _poll(pfds, nfds, timeout);
+}
+
+
+static int poll_with_pcm(struct pollfd *pfds, unsigned long nfds, int timeout)
+{
+ unsigned int k;
+ unsigned int nfds1;
+ int count;
+ struct pollfd pfds1[nfds + poll_fds_add + 16];
+
nfds1 = 0;
for (k = 0; k < nfds; ++k) {
int fd = pfds[k].fd;
- pfds[k].revents = 0;
- if (fd >= open_max || !fds[fd])
- goto _std1;
- switch (fds[fd]->class) {
- case FD_OSS_DSP:
- {
+ if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
unsigned short events = pfds[k].events;
int fmode = 0;
if ((events & (POLLIN|POLLOUT)) == (POLLIN|POLLOUT))
fmode = O_RDONLY;
else
fmode = O_WRONLY;
- nfds1 += lib_oss_pcm_poll_prepare(fd, fmode, &pfds1[nfds1]);
- direct = 0;
- break;
- }
- default:
- _std1:
- pfds1[nfds1].fd = pfds[k].fd;
- pfds1[nfds1].events = pfds[k].events;
- pfds1[nfds1].revents = 0;
+ count = lib_oss_pcm_poll_prepare(fd, fmode, &pfds1[nfds1]);
+ if (count < 0)
+ return -1;
+ nfds1 += count;
+ } else {
+ pfds1[nfds1] = pfds[k];
nfds1++;
- break;
+ }
+ if (nfds1 > nfds + poll_fds_add) {
+ fprintf(stderr, "alsa-oss: Pollfd overflow!\n");
+ errno = EINVAL;
+ return -1;
}
}
- if (direct)
- return _poll(pfds, nfds, timeout);
#ifdef DEBUG_POLL
if (oss_wrapper_debug) {
fprintf(stderr, "Orig enter ");
if (count <= 0)
return count;
nfds1 = 0;
- count1 = 0;
+ count = 0;
for (k = 0; k < nfds; ++k) {
int fd = pfds[k].fd;
unsigned int revents;
- if (fd >= open_max || !fds[fd])
- goto _std2;
- switch (fds[fd]->class) {
- case FD_OSS_DSP:
- {
+ if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
int result = lib_oss_pcm_poll_result(fd, &pfds1[nfds1]);
revents = 0;
if (result < 0) {
((result & OSS_WAIT_EVENT_WRITE) ? POLLOUT : 0);
}
nfds1 += lib_oss_pcm_poll_fds(fd);
- break;
- }
- default:
- _std2:
+ } else {
revents = pfds1[nfds1].revents;
nfds1++;
- break;
}
pfds[k].revents = revents;
if (revents)
- count1++;
+ count++;
}
#ifdef DEBUG_POLL
if (oss_wrapper_debug) {
dump_poll(pfds, nfds, timeout);
}
#endif
- return count1;
+ return count;
}
+static int select_with_pcm(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
+ struct timeval *timeout);
+
int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
struct timeval *timeout)
{
- fd_set _rfds1, _wfds1, _efds1;
- fd_set *rfds1, *wfds1, *efds1;
- int nfds1 = nfds;
- int count, count1;
int fd;
- int direct = 1;
if (!initialized)
initialize();
- if (rfds) {
+ for (fd = 0; fd < nfds; ++fd) {
+ int r = (rfds && FD_ISSET(fd, rfds));
+ int w = (wfds && FD_ISSET(fd, wfds));
+ int e = (efds && FD_ISSET(fd, efds));
+ if (!(r || w || e))
+ continue;
+ if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP)
+ return select_with_pcm(nfds, rfds, wfds, efds, timeout);
+ }
+ return _select(nfds, rfds, wfds, efds, timeout);
+}
+
+
+static int select_with_pcm(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
+ struct timeval *timeout)
+{
+ fd_set _rfds1, _wfds1, _efds1;
+ fd_set *rfds1, *wfds1, *efds1;
+ int fd;
+ int nfds1 = nfds;
+ int count;
+
+ if (rfds)
_rfds1 = *rfds;
- } else {
+ else
FD_ZERO(&_rfds1);
- }
rfds1 = &_rfds1;
- if (wfds) {
+ if (wfds)
_wfds1 = *wfds;
- } else {
+ else
FD_ZERO(&_wfds1);
- }
wfds1 = &_wfds1;
if (efds) {
_efds1 = *efds;
int e = (efds && FD_ISSET(fd, efds));
if (!(r || w || e))
continue;
- if (!fds[fd])
- continue;
- switch (fds[fd]->class) {
- case FD_OSS_DSP:
- {
+ if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
int res, fmode = 0;
if (r & w)
FD_CLR(fd, wfds1);
if (e)
FD_CLR(fd, efds1);
- direct = 0;
- break;
- }
- default:
- break;
}
}
- if (direct)
- return _select(nfds, rfds, wfds, efds, timeout);
#ifdef DEBUG_SELECT
if (oss_wrapper_debug) {
fprintf(stderr, "Orig enter ");
FD_ZERO(efds);
return 0;
}
- count1 = 0;
+ count = 0;
for (fd = 0; fd < nfds; ++fd) {
int r = (rfds && FD_ISSET(fd, rfds));
int w = (wfds && FD_ISSET(fd, wfds));
int r1, w1, e1;
if (!(r || w || e))
continue;
- if (!fds[fd])
- continue;
- switch (fds[fd]->class) {
- case FD_OSS_DSP:
- {
+ if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
int result = lib_oss_pcm_select_result(fd, rfds1, wfds1, efds1);
r1 = w1 = e1 = 0;
if (result < 0 && e) {
w1 = 1;
}
}
- break;
- }
- default:
+ } else {
r1 = (r && FD_ISSET(fd, rfds1));
w1 = (w && FD_ISSET(fd, wfds1));
e1 = (e && FD_ISSET(fd, efds1));
- break;
}
if (r && !r1)
FD_CLR(fd, rfds);
if (e && !e1)
FD_CLR(fd, efds);
if (r1 || w1 || e1)
- count1++;
+ count++;
}
#ifdef DEBUG_SELECT
if (oss_wrapper_debug) {
dump_select(nfds, rfds, wfds, efds, timeout);
}
#endif
- return count1;
+ return count;
}
if (!initialized)
initialize();
- if(!is_dsp_device(path))
- return _fopen (path, mode);
+ if (!is_dsp_device(path))
+ return _fopen(path, mode);
return fake_fopen(path, mode, 0);
}
if (!initialized)
initialize();
- if(!is_dsp_device(path))
- return _fopen (path, mode);
+ if (!is_dsp_device(path))
+ return _fopen(path, mode);
return fake_fopen(path, mode, O_LARGEFILE);
}
+#if 0
int dup(int fd)
{
return fcntl(fd, F_DUPFD, 0);
}
+#endif
+#if 0
int dup2(int fd, int fd2)
{
int save;
return fcntl(fd, F_DUPFD, fd2);
}
+#endif
int open64(const char *file, int oflag, ...)
{