]> code.delx.au - pulseaudio/blobdiff - src/utils/padsp.c
Merge remote branch 'origin/master-tx'
[pulseaudio] / src / utils / padsp.c
index 078b2e52a1a8d776930b19312290047c018b6988..41bfd741e618e8ff20e55d26ae946cc92d32abb6 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
@@ -8,7 +6,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
 #endif
 
 #include <pulse/pulseaudio.h>
+#include <pulse/gccmacro.h>
 #include <pulsecore/llist.h>
-#include <pulsecore/gccmacro.h>
+#include <pulsecore/core-util.h>
 
 /* On some systems SIOCINQ isn't defined, but FIONREAD is just an alias */
 #if !defined(SIOCINQ) && defined(FIONREAD)
 # define SIOCINQ FIONREAD
 #endif
 
+/* make sure gcc doesn't redefine open and friends as macros */
+#undef open
+#undef open64
+
 typedef enum {
     FD_INFO_MIXER,
     FD_INFO_STREAM,
@@ -298,7 +301,6 @@ static int padsp_disabled(void) {
     if (!sym_resolved) {
         sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__");
         sym_resolved = 1;
-
     }
     pthread_mutex_unlock(&func_mutex);
 
@@ -312,7 +314,7 @@ static int dsp_cloak_enable(void) {
     if (padsp_disabled() & 1)
         return 0;
 
-    if (getenv("PADSP_NO_DSP"))
+    if (getenv("PADSP_NO_DSP") || getenv("PULSE_INTERNAL"))
         return 0;
 
     return 1;
@@ -322,7 +324,7 @@ static int sndstat_cloak_enable(void) {
     if (padsp_disabled() & 2)
         return 0;
 
-    if (getenv("PADSP_NO_SNDSTAT"))
+    if (getenv("PADSP_NO_SNDSTAT") || getenv("PULSE_INTERNAL"))
         return 0;
 
     return 1;
@@ -332,7 +334,7 @@ static int mixer_cloak_enable(void) {
     if (padsp_disabled() & 4)
         return 0;
 
-    if (getenv("PADSP_NO_MIXER"))
+    if (getenv("PADSP_NO_MIXER") || getenv("PULSE_INTERNAL"))
         return 0;
 
     return 1;
@@ -421,7 +423,7 @@ static void fd_info_unref(fd_info *i) {
     pthread_mutex_lock(&i->mutex);
     assert(i->ref >= 1);
     r = --i->ref;
-        debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref);
     pthread_mutex_unlock(&i->mutex);
 
     if (r <= 0)
@@ -458,15 +460,16 @@ static void reset_params(fd_info *i) {
 }
 
 static const char *client_name(char *buf, size_t n) {
-    char p[PATH_MAX];
+    char *p;
     const char *e;
 
     if ((e = getenv("PADSP_CLIENT_NAME")))
         return e;
 
-    if (pa_get_binary_name(p, sizeof(p)))
+    if ((p = pa_get_binary_name_malloc())) {
         snprintf(buf, n, "OSS Emulation[%s]", p);
-    else
+        pa_xfree(p);
+    } else
         snprintf(buf, n, "OSS");
 
     return buf;
@@ -497,7 +500,6 @@ static void atfork_prepare(void) {
 
     pthread_mutex_lock(&func_mutex);
 
-
     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n");
 }
 
@@ -549,12 +551,14 @@ static void atfork_child(void) {
         }
 
         if (i->app_fd >= 0) {
-            close(i->app_fd);
+            LOAD_CLOSE_FUNC();
+            _close(i->app_fd);
             i->app_fd = -1;
         }
 
         if (i->thread_fd >= 0) {
-            close(i->thread_fd);
+            LOAD_CLOSE_FUNC();
+            _close(i->thread_fd);
             i->thread_fd = -1;
         }
 
@@ -747,7 +751,7 @@ static void fix_metrics(fd_info *i) {
     /* Number of fragments set? */
     if (i->n_fragments < 2) {
         if (i->fragment_size > 0) {
-            i->n_fragments = pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size;
+            i->n_fragments = (unsigned) (pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size);
             if (i->n_fragments < 2)
                 i->n_fragments = 2;
         } else
@@ -863,7 +867,7 @@ static int fd_info_copy_data(fd_info *i, int force) {
                 return -1;
             }
 
-            if (pa_stream_write(i->play_stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) {
+            if (pa_stream_write(i->play_stream, i->buf, (size_t) r, free, 0LL, PA_SEEK_RELATIVE) < 0) {
                 debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context)));
                 return -1;
             }
@@ -871,7 +875,7 @@ static int fd_info_copy_data(fd_info *i, int force) {
             i->buf = NULL;
 
             assert(n >= (size_t) r);
-            n -= r;
+            n -= (size_t) r;
         }
 
         if (n >= i->fragment_size)
@@ -915,7 +919,7 @@ static int fd_info_copy_data(fd_info *i, int force) {
             }
 
             assert((size_t)r <= len - i->rec_offset);
-            i->rec_offset += r;
+            i->rec_offset += (size_t) r;
 
             if (i->rec_offset == len) {
                 if (pa_stream_drop(i->rec_stream) < 0) {
@@ -926,7 +930,7 @@ static int fd_info_copy_data(fd_info *i, int force) {
             }
 
             assert(n >= (size_t) r);
-            n -= r;
+            n -= (size_t) r;
         }
 
         if (n >= i->fragment_size)
@@ -942,6 +946,10 @@ static int fd_info_copy_data(fd_info *i, int force) {
         api->io_enable(i->io_event, i->io_flags);
     }
 
+    /* So, we emptied the socket now, let's tell dsp_empty_socket()
+     * about this */
+    pa_threaded_mainloop_signal(i->mainloop, 0);
+
     return 0;
 }
 
@@ -997,12 +1005,12 @@ static int create_playback_stream(fd_info *i) {
     pa_stream_set_latency_update_callback(i->play_stream, stream_latency_update_cb, i);
 
     memset(&attr, 0, sizeof(attr));
-    attr.maxlength = i->fragment_size * (i->n_fragments+1);
-    attr.tlength = i->fragment_size * i->n_fragments;
-    attr.prebuf = i->fragment_size;
-    attr.minreq = i->fragment_size;
+    attr.maxlength = (uint32_t) (i->fragment_size * (i->n_fragments+1));
+    attr.tlength = (uint32_t) (i->fragment_size * i->n_fragments);
+    attr.prebuf = (uint32_t) i->fragment_size;
+    attr.minreq = (uint32_t) i->fragment_size;
 
-    flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE;
+    flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_EARLY_REQUESTS;
     if (i->play_precork) {
         flags |= PA_STREAM_START_CORKED;
         debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n");
@@ -1012,9 +1020,9 @@ static int create_playback_stream(fd_info *i) {
         goto fail;
     }
 
-    n = i->fragment_size;
+    n = (int) i->fragment_size;
     setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
-    n = i->fragment_size;
+    n = (int) i->fragment_size;
     setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
 
     return 0;
@@ -1041,8 +1049,8 @@ static int create_record_stream(fd_info *i) {
     pa_stream_set_latency_update_callback(i->rec_stream, stream_latency_update_cb, i);
 
     memset(&attr, 0, sizeof(attr));
-    attr.maxlength = i->fragment_size * (i->n_fragments+1);
-    attr.fragsize = i->fragment_size;
+    attr.maxlength = (uint32_t) (i->fragment_size * (i->n_fragments+1));
+    attr.fragsize = (uint32_t) i->fragment_size;
 
     flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE;
     if (i->rec_precork) {
@@ -1054,9 +1062,9 @@ static int create_record_stream(fd_info *i) {
         goto fail;
     }
 
-    n = i->fragment_size;
+    n = (int) i->fragment_size;
     setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
-    n = i->fragment_size;
+    n = (int) i->fragment_size;
     setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
 
     return 0;
@@ -1196,7 +1204,7 @@ fail:
 static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, void *userdata) {
     fd_info *i = userdata;
 
-    if (!si && eol < 0) {
+    if (!si || eol < 0) {
         i->operation_success = 0;
         pa_threaded_mainloop_signal(i->mainloop, 0);
         return;
@@ -1218,7 +1226,7 @@ static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, v
 static void source_info_cb(pa_context *context, const pa_source_info *si, int eol, void *userdata) {
     fd_info *i = userdata;
 
-    if (!si && eol < 0) {
+    if (!si || eol < 0) {
         i->operation_success = 0;
         pa_threaded_mainloop_signal(i->mainloop, 0);
         return;
@@ -1436,35 +1444,23 @@ fail:
     return -1;
 }
 
-#undef open
-int open(const char *filename, int flags, ...) {
-    va_list args;
-    mode_t mode = 0;
+static int real_open(const char *filename, int flags, mode_t mode) {
     int r, _errno = 0;
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename);
-
-    va_start(args, flags);
-    if (flags & O_CREAT) {
-      if (sizeof(mode_t) < sizeof(int))
-        mode = va_arg(args, int);
-      else
-        mode = va_arg(args, mode_t);
-    }
-    va_end(args);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename?filename:"NULL");
 
     if (!function_enter()) {
         LOAD_OPEN_FUNC();
         return _open(filename, flags, mode);
     }
 
-    if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) {
+    if (filename && dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0))
         r = dsp_open(flags, &_errno);
-    } else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) {
+    else if (filename && mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0)
         r = mixer_open(flags, &_errno);
-    } else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) {
+    else if (filename && sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0)
         r = sndstat_open(flags, &_errno);
-    else {
+    else {
         function_exit();
         LOAD_OPEN_FUNC();
         return _open(filename, flags, mode);
@@ -1478,6 +1474,22 @@ int open(const char *filename, int flags, ...) {
     return r;
 }
 
+int open(const char *filename, int flags, ...) {
+    va_list args;
+    mode_t mode = 0;
+
+    if (flags & O_CREAT) {
+        va_start(args, flags);
+        if (sizeof(mode_t) < sizeof(int))
+            mode = (mode_t) va_arg(args, int);
+        else
+            mode = va_arg(args, mode_t);
+        va_end(args);
+    }
+
+    return real_open(filename, flags, mode);
+}
+
 static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
     int ret = -1;
 
@@ -1809,7 +1821,7 @@ fail:
 
     pa_threaded_mainloop_unlock(i->mainloop);
 
-    return 0;
+    return r;
 }
 
 static int dsp_trigger(fd_info *i) {
@@ -1852,7 +1864,7 @@ fail:
 
     pa_threaded_mainloop_unlock(i->mainloop);
 
-    return 0;
+    return r;
 }
 
 static int dsp_cork(fd_info *i, pa_stream *s, int b) {
@@ -1890,7 +1902,7 @@ fail:
 
     pa_threaded_mainloop_unlock(i->mainloop);
 
-    return 0;
+    return r;
 }
 
 static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
@@ -2245,7 +2257,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno)
             for (;;) {
                 pa_usec_t usec;
 
-                PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop);
+                PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop2);
 
                 if (pa_stream_get_time(i->play_stream, &usec) >= 0) {
                     size_t k = pa_usec_to_bytes(usec, &i->sample_spec);
@@ -2267,6 +2279,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno)
                 pa_threaded_mainloop_wait(i->mainloop);
             }
 
+        exit_loop2:
+
             pa_threaded_mainloop_unlock(i->mainloop);
 
             debug(DEBUG_LEVEL_NORMAL, __FILE__": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info->bytes, info->blocks, info->ptr);
@@ -2284,7 +2298,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno)
             break;
 
         default:
-            debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);
+            /* Mixer ioctls are valid on /dev/dsp aswell */
+            return mixer_ioctl(i, request, argp, _errno);
 
 inval:
             *_errno = EINVAL;
@@ -2298,7 +2313,11 @@ fail:
     return ret;
 }
 
+#ifdef sun
+int ioctl(int fd, int request, ...) {
+#else
 int ioctl(int fd, unsigned long request, ...) {
+#endif
     fd_info *i;
     va_list args;
     void *argp;
@@ -2362,23 +2381,18 @@ int close(int fd) {
 
 int access(const char *pathname, int mode) {
 
-    if (!pathname) {
-        /* Firefox needs this. See #27 */
-        errno = EFAULT;
-        return -1;
-    }
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname?pathname:"NULL");
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname);
-
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    if (!pathname ||
+        (strcmp(pathname, "/dev/dsp") != 0 &&
+         strcmp(pathname, "/dev/adsp") != 0 &&
+         strcmp(pathname, "/dev/sndstat") != 0 &&
+         strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_ACCESS_FUNC();
         return _access(pathname, mode);
     }
 
-    if (mode & (W_OK | X_OK)) {
+    if (mode & X_OK) {
         debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = EACCESS\n", pathname, mode);
         errno = EACCES;
         return -1;
@@ -2397,16 +2411,13 @@ int stat(const char *pathname, struct stat *buf) {
 #endif
     int ret;
 
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
-        debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname);
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
+        debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname?pathname:"NULL");
         LOAD_STAT_FUNC();
         return _stat(pathname, buf);
     }
@@ -2455,17 +2466,14 @@ int stat64(const char *pathname, struct stat64 *buf) {
     struct stat oldbuf;
     int ret;
 
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname?pathname:"NULL");
 
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_STAT64_FUNC();
         return _stat64(pathname, buf);
     }
@@ -2495,22 +2503,27 @@ int open64(const char *filename, int flags, ...) {
     va_list args;
     mode_t mode = 0;
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename?filename:"NULL");
 
-    va_start(args, flags);
-    if (flags & O_CREAT)
-        mode = va_arg(args, mode_t);
-    va_end(args);
+    if (flags & O_CREAT) {
+        va_start(args, flags);
+        if (sizeof(mode_t) < sizeof(int))
+            mode = va_arg(args, int);
+        else
+            mode = va_arg(args, mode_t);
+        va_end(args);
+    }
 
-    if (strcmp(filename, "/dev/dsp") != 0 &&
-        strcmp(filename, "/dev/adsp") != 0 &&
-        strcmp(filename, "/dev/sndstat") != 0 &&
-        strcmp(filename, "/dev/mixer") != 0) {
+    if (!filename ||
+        ( strcmp(filename, "/dev/dsp") != 0 &&
+          strcmp(filename, "/dev/adsp") != 0 &&
+          strcmp(filename, "/dev/sndstat") != 0 &&
+          strcmp(filename, "/dev/mixer") != 0 )) {
         LOAD_OPEN64_FUNC();
         return _open64(filename, flags, mode);
     }
 
-    return open(filename, flags, mode);
+    return real_open(filename, flags, mode);
 }
 
 #endif
@@ -2518,17 +2531,14 @@ int open64(const char *filename, int flags, ...) {
 #ifdef _STAT_VER
 
 int __xstat(int ver, const char *pathname, struct stat *buf) {
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname);
-
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname?pathname:"NULL");
+
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_XSTAT_FUNC();
         return ___xstat(ver, pathname, buf);
     }
@@ -2544,17 +2554,14 @@ int __xstat(int ver, const char *pathname, struct stat *buf) {
 #ifdef HAVE_OPEN64
 
 int __xstat64(int ver, const char *pathname, struct stat64 *buf) {
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname);
-
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname?pathname:"NULL");
+
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_XSTAT64_FUNC();
         return ___xstat64(ver, pathname, buf);
     }
@@ -2576,12 +2583,14 @@ FILE* fopen(const char *filename, const char *mode) {
     int fd;
     mode_t m;
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename?filename:"NULL");
 
-    if (strcmp(filename, "/dev/dsp") != 0 &&
-        strcmp(filename, "/dev/adsp") != 0 &&
-        strcmp(filename, "/dev/sndstat") != 0 &&
-        strcmp(filename, "/dev/mixer") != 0) {
+    if (!filename ||
+        !mode ||
+        ( strcmp(filename, "/dev/dsp") != 0 &&
+          strcmp(filename, "/dev/adsp") != 0 &&
+          strcmp(filename, "/dev/sndstat") != 0 &&
+          strcmp(filename, "/dev/mixer") != 0 )) {
         LOAD_FOPEN_FUNC();
         return _fopen(filename, mode);
     }
@@ -2602,7 +2611,7 @@ FILE* fopen(const char *filename, const char *mode) {
     if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+'))
         m = O_RDWR;
 
-    if ((fd = open(filename, m)) < 0)
+    if ((fd = real_open(filename, m, 0)) < 0)
         return NULL;
 
     if (!(f = fdopen(fd, mode))) {
@@ -2617,12 +2626,14 @@ FILE* fopen(const char *filename, const char *mode) {
 
 FILE *fopen64(const char *filename, const char *mode) {
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename?filename:"NULL");
 
-    if (strcmp(filename, "/dev/dsp") != 0 &&
-        strcmp(filename, "/dev/adsp") != 0 &&
-        strcmp(filename, "/dev/sndstat") != 0 &&
-        strcmp(filename, "/dev/mixer") != 0) {
+    if (!filename ||
+        !mode ||
+        ( strcmp(filename, "/dev/dsp") != 0 &&
+          strcmp(filename, "/dev/adsp") != 0 &&
+          strcmp(filename, "/dev/sndstat") != 0 &&
+          strcmp(filename, "/dev/mixer") != 0 )) {
         LOAD_FOPEN64_FUNC();
         return _fopen64(filename, mode);
     }