shithub: choc

Download patch

ref: eba59fdf4448693b73b19ba12a11bff265d4ddfc
parent: 1eeceb39814a1a0b13cab79a675e81a27477c9e8
author: Simon Howard <fraggle@gmail.com>
date: Fri Mar 9 18:30:46 EST 2007

Add pcsound Linux driver.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 851

--- a/configure.in
+++ b/configure.in
@@ -22,6 +22,8 @@
         CFLAGS="-O$OPT_LEVEL -g -Wall $orig_CFLAGS"
 fi
 
+AC_CHECK_HEADERS([linux/kd.h])
+
 AM_PATH_SDL(1.1.3)
 
 AC_CHECK_LIB(SDL_mixer,Mix_LoadMUS,[
--- a/pcsound/Makefile.am
+++ b/pcsound/Makefile.am
@@ -6,5 +6,6 @@
 libpcsound_a_SOURCES =                            \
         pcsound.c           pcsound.h             \
         pcsound_sdl.c                             \
+        pcsound_linux.c                           \
         pcsound_win32.c     
 
--- a/pcsound/pcsound.c
+++ b/pcsound/pcsound.c
@@ -27,15 +27,24 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "config.h"
 #include "pcsound.h"
 
 #ifdef _WIN32
 extern pcsound_driver_t pcsound_win32_driver;
 #endif
+
+#ifdef HAVE_LINUX_KD_H
+extern pcsound_driver_t pcsound_linux_driver;
+#endif
+
 extern pcsound_driver_t pcsound_sdl_driver;
 
 static pcsound_driver_t *drivers[] = 
 {
+#ifdef HAVE_LINUX_KD_H
+    &pcsound_linux_driver,
+#endif
 #ifdef _WIN32
     &pcsound_win32_driver,
 #endif
--- a/pcsound/pcsound.h
+++ b/pcsound/pcsound.h
@@ -26,6 +26,8 @@
 #ifndef PCSOUND_H
 #define PCSOUND_H
 
+#define PCSOUND_8253_FREQUENCY 1193280
+
 typedef struct pcsound_driver_s pcsound_driver_t;
 typedef void (*pcsound_callback_func)(int *duration, int *frequency);
 typedef int (*pcsound_init_func)(pcsound_callback_func callback);
--- /dev/null
+++ b/pcsound/pcsound_linux.c
@@ -1,0 +1,126 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2007 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//    PC speaker driver for Linux.
+//
+//-----------------------------------------------------------------------------
+
+#include "config.h"
+
+#ifdef HAVE_LINUX_KD_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/kd.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "SDL.h"
+#include "SDL_thread.h"
+
+#include "pcsound.h"
+
+#define CONSOLE_DEVICE "/dev/console"
+
+static int console_handle;
+static pcsound_callback_func callback;
+static int sound_thread_running = 0;
+static SDL_Thread *sound_thread_handle;
+
+static int SoundThread(void *unused)
+{
+    int frequency;
+    int duration;
+    int cycles;
+    
+    while (sound_thread_running)
+    {
+        callback(&duration, &frequency);
+
+        if (frequency != 0) 
+        {
+            cycles = PCSOUND_8253_FREQUENCY / frequency;
+        }
+        else
+        {
+            cycles = 0;
+        }
+
+        ioctl(console_handle, KIOCSOUND, cycles);
+
+        usleep(duration * 1000);
+    }
+
+    return 0;
+}
+
+static int PCSound_Linux_Init(pcsound_callback_func callback_func)
+{
+    // Try to open the console
+
+    console_handle = open(CONSOLE_DEVICE, O_WRONLY);
+
+    if (console_handle == -1)
+    {
+        // Don't have permissions for the console device?
+
+	fprintf(stderr, "PCSound_Linux_Init: Failed to open '%s': %s\n",
+			CONSOLE_DEVICE, strerror(errno));
+        return 0;
+    }
+
+    if (ioctl(console_handle, KIOCSOUND, 0) < 0)
+    {
+        // KIOCSOUND not supported: non-PC linux?
+
+        close(console_handle);
+        return 0;
+    }
+
+    // Start a thread up to generate PC speaker output
+    
+    callback = callback_func;
+    sound_thread_running = 1;
+
+    sound_thread_handle = SDL_CreateThread(SoundThread, NULL);
+    
+    return 1;
+}
+
+static void PCSound_Linux_Shutdown(void)
+{
+    sound_thread_running = 0;
+    SDL_WaitThread(sound_thread_handle, NULL);
+    close(console_handle);
+}
+
+pcsound_driver_t pcsound_linux_driver =
+{
+    "Linux",
+    PCSound_Linux_Init,
+    PCSound_Linux_Shutdown,
+};
+
+#endif /* #ifdef HAVE_LINUX_KD_H */
+