"Fossies" - the Fresh Open Source Software Archive

Member "alsa-oss-1.1.8/oss-redir/oss-redir.c" (7 Jan 2019, 7138 Bytes) of package /linux/misc/alsa-oss-1.1.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "oss-redir.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.0.28_vs_1.1.6.

    1 /*
    2  *  OSS Redirector
    3  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
    4  *
    5  *
    6  *   This program is free software; you can redistribute it and/or modify
    7  *   it under the terms of the GNU General Public License as published by
    8  *   the Free Software Foundation; either version 2 of the License, or
    9  *   (at your option) any later version.
   10  *
   11  *   This program is distributed in the hope that it will be useful,
   12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *   GNU General Public License for more details.
   15  *
   16  *   You should have received a copy of the GNU General Public License
   17  *   along with this program; if not, write to the Free Software
   18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   19  *
   20  */
   21 
   22 #define _GNU_SOURCE
   23 
   24 #include "oss-redir.h"
   25 #include <sys/poll.h>
   26 #include <sys/ioctl.h>
   27 #include <sys/mman.h>
   28 #include <stdio.h>
   29 #include <stdlib.h>
   30 #include <string.h>
   31 #include <fcntl.h>
   32 #include <unistd.h>
   33 #include <dlfcn.h>
   34 #include <errno.h>
   35 #include <linux/soundcard.h>
   36 
   37 static int initialized = 0;
   38 static int native_oss = 1;
   39 static int open_count = 0;
   40 static char hal[64];
   41 static void *dl_handle = NULL;
   42 
   43 static void initialize(void);
   44 
   45 static int (*x_oss_pcm_open)(const char *pathname, int flags);
   46 static int (*x_oss_pcm_close)(int fd);
   47 int (*oss_pcm_nonblock)(int fd, int nonblock);
   48 ssize_t (*oss_pcm_read)(int fd, void *buf, size_t count);
   49 ssize_t (*oss_pcm_write)(int fd, const void *buf, size_t count);
   50 void * (*oss_pcm_mmap)(void *start, size_t length, int prot, int flags, int fd, off_t offset);
   51 int (*oss_pcm_munmap)(void *start, size_t length);
   52 int (*oss_pcm_ioctl)(int fd, unsigned long int request, ...);
   53 int (*oss_pcm_select_prepare)(int fd, int fmode, fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
   54 int (*oss_pcm_select_result)(int fd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
   55 int (*oss_pcm_poll_fds)(int fd);
   56 int (*oss_pcm_poll_prepare)(int fd, int fmode, struct pollfd *ufds);
   57 int (*oss_pcm_poll_result)(int fd, struct pollfd *ufds);
   58 
   59 static int (*x_oss_mixer_open)(const char *pathname, int flags);
   60 static int (*x_oss_mixer_close)(int fd);
   61 int (*oss_mixer_ioctl)(int fd, unsigned long int request, ...);
   62 
   63 static int native_pcm_nonblock(int fd, int nonblock)
   64 {
   65     long flags;
   66 
   67     if ((flags = fcntl(fd, F_GETFL)) < 0)
   68         return -1;
   69     if (nonblock)
   70         flags |= O_NONBLOCK;
   71     else
   72         flags &= ~O_NONBLOCK;
   73     if (fcntl(fd, F_SETFL, flags) < 0)
   74         return -1;
   75     return 0;
   76 }
   77 
   78 static int native_pcm_select_prepare(int fd, int fmode, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
   79 {
   80     if (fd < 0)
   81         return -EINVAL;
   82     if ((fmode & O_ACCMODE) != O_WRONLY && readfds) {
   83         FD_SET(fd, readfds);
   84         if (exceptfds)
   85             FD_SET(fd, exceptfds);
   86     }
   87     if ((fmode & O_ACCMODE) != O_RDONLY && writefds) {
   88         FD_SET(fd, writefds);
   89         if (exceptfds)
   90             FD_SET(fd, exceptfds);
   91     }
   92     return fd;
   93 }
   94 
   95 static int native_pcm_select_result(int fd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
   96 {
   97     int result = 0;
   98 
   99     if (fd < 0)
  100         return -EINVAL;
  101     if (readfds && FD_ISSET(fd, readfds))
  102         result |= OSS_WAIT_EVENT_READ;
  103     if (writefds && FD_ISSET(fd, writefds))
  104         result |= OSS_WAIT_EVENT_WRITE;
  105     if (exceptfds && FD_ISSET(fd, exceptfds))
  106         result |= OSS_WAIT_EVENT_ERROR;
  107     return result;
  108 }
  109 
  110 static int native_pcm_poll_fds(int fd)
  111 {
  112     if (fd < 0)
  113         return -EINVAL;
  114     return 1;
  115 }
  116 
  117 static int native_pcm_poll_prepare(int fd, int fmode, struct pollfd *ufds)
  118 {
  119     if (fd < 0)
  120         return -EINVAL;
  121     ufds->fd = fd;
  122     ufds->events = ((fmode & O_ACCMODE) == O_WRONLY ? 0 : POLLIN) |
  123                ((fmode & O_ACCMODE) == O_RDONLY ? 0 : POLLOUT) | POLLERR;
  124     return 1;
  125 }
  126 
  127 static int native_pcm_poll_result(int fd, struct pollfd *ufds)
  128 {
  129     int result = 0;
  130 
  131     if (fd < 0)
  132         return -EINVAL;
  133     if (ufds->events & POLLIN)
  134         result |= OSS_WAIT_EVENT_READ;
  135     if (ufds->events & POLLOUT)
  136         result |= OSS_WAIT_EVENT_WRITE;
  137     if (ufds->events & POLLERR)
  138         result |= OSS_WAIT_EVENT_ERROR;
  139     return result;
  140 }
  141 
  142 static inline void check_initialized(void)
  143 {
  144     if (!initialized)
  145         initialize();
  146 }
  147 
  148 int oss_pcm_open(const char *pathname, int flags, ...)
  149 {
  150     int result;
  151 
  152     check_initialized();
  153     if (native_oss)
  154         return open(pathname, flags);
  155     result = x_oss_pcm_open(pathname, flags);
  156     if (result >= 0) {
  157         open_count++;
  158     } else {
  159         if (open_count == 0) {
  160             dlclose(dl_handle);
  161             dl_handle = NULL;
  162         }
  163     }
  164     return result;
  165 }
  166 
  167 int oss_pcm_close(int fd)
  168 {
  169     int result;
  170 
  171     if (native_oss)
  172         return close(fd);
  173     result = x_oss_pcm_close(fd);
  174     if (--open_count) {
  175         dlclose(dl_handle);
  176         dl_handle = NULL;
  177     }
  178     return result;
  179 }
  180 
  181 int oss_mixer_open(const char *pathname, int flags, ...)
  182 {
  183     int result;
  184 
  185     check_initialized();
  186     if (native_oss)
  187         return open(pathname, flags);
  188     result = x_oss_mixer_open(pathname, flags);
  189     if (result >= 0) {
  190         open_count++;
  191     } else {
  192         if (open_count == 0) {
  193             dlclose(dl_handle);
  194             dl_handle = NULL;
  195         }
  196     }
  197     return result;
  198 }
  199 
  200 int oss_mixer_close(int fd)
  201 {
  202     int result;
  203 
  204     if (fd < 0)
  205         return -EINVAL;
  206     if (native_oss)
  207         return close(fd);
  208     result = x_oss_mixer_close(fd);
  209     if (--open_count) {
  210         dlclose(dl_handle);
  211         dl_handle = NULL;
  212     }
  213     return result;
  214 }
  215 
  216 static void initialize(void)
  217 {
  218     char *s = getenv("OSS_REDIRECTOR");
  219     if (s) {
  220         strncpy(hal, s, sizeof(hal));
  221         hal[sizeof(hal)-1] = '\0';
  222         if (!strcasecmp(hal, "oss"))
  223             native_oss = 1;
  224         else
  225             native_oss = 0;
  226     } else {
  227         native_oss = 1;
  228     }
  229     if (native_oss) {
  230           __native:
  231             oss_pcm_nonblock = native_pcm_nonblock;
  232         oss_pcm_read = read;
  233         oss_pcm_write = write;
  234         oss_pcm_mmap = mmap;
  235         oss_pcm_munmap = munmap;
  236         oss_pcm_ioctl = ioctl;
  237         oss_pcm_select_prepare = native_pcm_select_prepare;
  238         oss_pcm_select_result = native_pcm_select_result;
  239         oss_pcm_poll_fds = native_pcm_poll_fds;
  240         oss_pcm_poll_prepare = native_pcm_poll_prepare;
  241         oss_pcm_poll_result = native_pcm_poll_result;
  242         oss_mixer_ioctl = ioctl;
  243     } else {
  244         dl_handle = dlopen(hal, RTLD_NOW);
  245         if (dl_handle == NULL) {
  246             fprintf(stderr, "ERROR: dlopen failed for sound (OSS) redirector: %s\n", dlerror());
  247             fprintf(stderr, "       reverting to native OSS mode\n");
  248             native_oss = 1;
  249             goto __native;
  250         }
  251         x_oss_pcm_open = dlsym(dl_handle, "lib_oss_pcm_open");
  252         x_oss_pcm_close = dlsym(dl_handle, "lib_oss_pcm_close");
  253         oss_pcm_nonblock = dlsym(dl_handle, "lib_oss_pcm_nonblock");
  254         oss_pcm_read = dlsym(dl_handle, "lib_oss_pcm_read");
  255         oss_pcm_write = dlsym(dl_handle, "lib_oss_pcm_write");
  256         oss_pcm_mmap = dlsym(dl_handle, "lib_oss_pcm_mmap");
  257         oss_pcm_munmap = dlsym(dl_handle, "lib_oss_pcm_munmap");
  258         oss_pcm_ioctl = dlsym(dl_handle, "lib_oss_pcm_ioctl");
  259         oss_pcm_select_prepare = dlsym(dl_handle, "lib_oss_select_prepare");
  260         oss_pcm_select_result = dlsym(dl_handle, "lib_oss_select_result");
  261         oss_pcm_poll_fds = dlsym(dl_handle, "lib_oss_poll_fds");
  262         oss_pcm_poll_prepare = dlsym(dl_handle, "lib_oss_poll_prepare");
  263         oss_pcm_poll_result = dlsym(dl_handle, "lib_oss_poll_result");
  264         x_oss_mixer_open = dlsym(dl_handle, "lib_oss_mixer_open");
  265         x_oss_mixer_close = dlsym(dl_handle, "lib_oss_mixer_close");
  266         oss_mixer_ioctl = dlsym(dl_handle, "lib_oss_mixer_ioctl");
  267     }
  268 }