beep.cpp

00001 
00002 /***************************************************************************
00003  *  beep.cpp - Beeper utility class
00004  *
00005  *  Created: Sun Apr 11 19:41:23 2010
00006  *  Copyright  2006-2010  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include "beep.h"
00025 
00026 #include <cstdio>
00027 #include <cerrno>
00028 #include <termios.h>
00029 #include <sys/types.h>
00030 #include <fcntl.h>
00031 #include <cstring>
00032 #include <sys/ioctl.h>
00033 #include <linux/kd.h>
00034 #include <unistd.h>
00035 
00036 
00037 /* From console_ioctl man page, explained in the beep too by
00038  * Johnathan Nightingale:
00039  * This number represents the fixed frequency of the original PC XT's
00040  * timer chip (the 8254 AFAIR), which is approximately 1.193 MHz. This
00041  * number is divided with the desired frequency to obtain a counter value,
00042  * that is subsequently fed into the timer chip, tied to the PC speaker.
00043  * The chip decreases this counter at every tick (1.193 MHz) and when it
00044  * reaches zero, it toggles the state of the speaker (on/off, or in/out),
00045  * resets the counter to the original value, and starts over. The end
00046  * result of this is a tone at approximately the desired frequency. :)
00047  */
00048 #define CLOCK_TICK_RATE 1193180
00049 
00050 #define CONSOLE_FILE "/dev/console"
00051 
00052 /** @class BeepController "beep.h"
00053  * Simple speaker beep controller.
00054  * @author Tim Niemueller
00055  */
00056 
00057 /** Constructor. */
00058 BeepController::BeepController()
00059 {
00060   __disable_beeping = false;
00061 }
00062 
00063 /** Enable beeping.
00064  * @param freq frequency to beep with
00065  */
00066 void
00067 BeepController::beep_on(float freq)
00068 {
00069   if (__disable_beeping)  return;
00070     
00071   int beep_fd = open(CONSOLE_FILE, O_WRONLY);
00072   if (beep_fd == -1) {
00073     char errstr[1024];
00074     strerror_r(errno, errstr, sizeof(errstr));
00075     //logger->log_warn(name(), "Could not open console (%s). "
00076     //               "Disabling warning beeps.", errstr);
00077     __disable_beeping = true;
00078   } else {
00079     if (ioctl(beep_fd, KIOCSOUND, (int)(CLOCK_TICK_RATE/freq)) < 0) {
00080       //logger->log_warn(name(), "Starting to beep failed. Disabling warning beeps.");
00081       __disable_beeping = true;
00082     }
00083     close(beep_fd);
00084   }
00085 }
00086 
00087 
00088 /** Disable beeping. */
00089 void
00090 BeepController::beep_off()
00091 {
00092   if (__disable_beeping)  return;
00093 
00094   int beep_fd = open(CONSOLE_FILE, O_WRONLY);
00095   if (beep_fd == -1) {
00096     char errstr[1024];
00097     strerror_r(errno, errstr, sizeof(errstr));
00098     //logger->log_warn(name(), "Could not open console (%s) [stop]. "
00099     //               "Disabling warning beeps.", errstr);
00100     __disable_beeping = true;
00101   } else {
00102     if (ioctl(beep_fd, KIOCSOUND, 0) < 0) {
00103       //logger->log_warn(name(), "Stopping beeping failed. "
00104       //               "Disabling warning beeps.");
00105       __disable_beeping = true;
00106     }
00107     close(beep_fd);
00108   }
00109 }