Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

ArSoundPlayer.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 
00028 #include "ArExport.h"
00029 #include "ArSoundPlayer.h"
00030 #include "ArLog.h"
00031 
00032 int ArSoundPlayer::myPlayChildPID = -1;
00033 ArGlobalRetFunctor2<bool, const char*, const char*> ArSoundPlayer::ourPlayWavFileCB(&ArSoundPlayer::playWavFile);
00034 ArGlobalFunctor ArSoundPlayer::ourStopPlayingCB(&ArSoundPlayer::stopPlaying);
00035 
00036 ArRetFunctor2<bool, const char*, const char*>* ArSoundPlayer::getPlayWavFileCallback() 
00037 {
00038   return &ourPlayWavFileCB;
00039 }
00040 
00041 ArFunctor* ArSoundPlayer::getStopPlayingCallback()
00042 {
00043   return &ourStopPlayingCB;
00044 }
00045 
00046 
00047 #ifdef WIN32
00048 
00049       /* Windows: */
00050 
00051 #include <assert.h>
00052 
00053 bool ArSoundPlayer::playWavFile(const char* filename, const char* params) 
00054 {
00055   return (PlaySound(filename, NULL, SND_FILENAME) == TRUE);
00056 }
00057 
00058 bool ArSoundPlayer::playNativeFile(const char* filename, const char* params)
00059 {
00060   /* WAV is the Windows native format */
00061   return playWavFile(filename, 0);
00062 }
00063 
00064 void ArSoundPlayer::stopPlaying()
00065 {
00066   PlaySound(NULL, NULL, NULL);
00067 }
00068 
00069 
00070 bool ArSoundPlayer::playSoundPCM16(char* data, int numSamples)
00071 {
00072   ArLog::log(ArLog::Terse, "INTERNAL ERROR: ArSoundPlayer::playSoundPCM16() is not implemented for Windows yet! Bug reed@activmedia.com about it!");
00073   assert(false);
00074 
00075   return false;
00076 }
00077 
00078 #else
00079 
00080       /* Linux: */
00081 
00082 #include <stdio.h>
00083 #include <sys/ioctl.h>
00084 #include <sys/types.h>
00085 #include <sys/stat.h>
00086 #include <sys/wait.h>
00087 #include <fcntl.h>
00088 #include <sys/soundcard.h>
00089 //#include <linux/soundcard.h>
00090 #include <unistd.h>
00091 #include <errno.h>
00092 
00093 
00094 
00095 bool ArSoundPlayer::playNativeFile(const char* filename, const char* params)
00096 {
00097   int snd_fd = open("/dev/dsp", O_WRONLY); // | O_NONBLOCK);
00098   if(snd_fd < 0) {
00099     return false;
00100   }
00101   int file_fd = open(filename, O_RDONLY);
00102   if(file_fd < 0)
00103   {
00104     perror("ArSoundPlayer::playNativeFile");
00105     return false;
00106   }
00107   int len;
00108   const int buflen = 512;
00109   char buf[buflen];
00110   while((len = read(file_fd, buf, buflen)) > 0)
00111   {
00112     if (write(snd_fd, buf, len) != len) {
00113       perror("ArSoundPlayer::playNativeFile");
00114     }
00115   }
00116   close(file_fd);
00117   close(snd_fd);
00118   return true;
00119 }
00120 
00121 bool ArSoundPlayer::playWavFile(const char* filename, const char* params)
00122 {
00123   char* prog = NULL;
00124   prog = getenv("PLAY_WAV");
00125   if(prog == NULL)
00126     prog = "play";
00127   myPlayChildPID = fork();
00128   if(myPlayChildPID == -1) 
00129   {
00130     ArLog::log(ArLog::Terse, "ArSoundPlayer: error forking!");
00131     perror("Aria: ArSoundPlayer");
00132     return false;
00133   }
00134   if(myPlayChildPID == 0)
00135   {
00136     // child process: execute sox
00137     ArLog::log(ArLog::Verbose, "ArSoundPlayer: executing \"%s\" with argument \"%s\" in child process...\n", prog, filename);
00138     if(execlp(prog, prog, filename, 0) < 0) 
00139     {
00140       perror("Aria: ArSoundPlayer: Error executing Wav file playback program");
00141       exit(-1);
00142     }
00143   } 
00144   // parent process: wait for child to finish
00145   ArLog::log(ArLog::Verbose, "ArSoundPlayer: created child process %d to play wav file \"%s\".", 
00146       myPlayChildPID, filename);
00147   int status;
00148   waitpid(myPlayChildPID, &status, 0);
00149   if(WEXITSTATUS(status) != 0) {
00150     ArLog::log(ArLog::Terse, "ArSoundPlayer: Error: Wav file playback program \"%s\" exited with error code %d.", prog, WEXITSTATUS(status));
00151     myPlayChildPID = -1;
00152     return false;
00153   }
00154   myPlayChildPID = -1;
00155   return true;
00156 }
00157 
00158 
00159 
00160 void ArSoundPlayer::stopPlaying()
00161 {
00162   // Kill a child processes (created by playWavFile) if it exists.
00163   if(myPlayChildPID > 0)
00164   {
00165     ArLog::log(ArLog::Verbose, "ArSoundPlayer: Sending SIGTERM to child process %d.", myPlayChildPID);
00166     kill(myPlayChildPID, SIGTERM);
00167   }
00168 }
00169 
00170 
00171 bool ArSoundPlayer::playSoundPCM16(char* data, int numSamples)
00172 {
00173   //ArLog::log(ArLog::Normal, "ArSoundPlayer::playSoundPCM16[linux]: opening sound device.");
00174   int fd = open("/dev/dsp", O_WRONLY); // | O_NONBLOCK);
00175   if(fd < 0)
00176     return false;
00177   int arg = AFMT_S16_LE;
00178   if(ioctl(fd, SNDCTL_DSP_SETFMT, &arg) != 0)
00179   {
00180     close(fd);
00181     return false;
00182   }
00183   arg = 0;
00184   if(ioctl(fd, SNDCTL_DSP_STEREO, &arg) != 0)
00185   {
00186     close(fd);
00187     return false;
00188   }
00189   arg = 16000;
00190   if(ioctl(fd, SNDCTL_DSP_SPEED, &arg) != 0)
00191   {
00192     close(fd);
00193     return false;
00194   }
00195   //ArLog::log(ArLog::Normal, "ArSoundPlayer::playSoundPCM16[linux]: writing %d bytes to sound device.", 2*numSamples);
00196   int r;
00197   if((r = write(fd, data, 2*numSamples) < 0))
00198   {
00199     close(fd);
00200     return false;
00201   }
00202   close(fd);
00203   ArLog::log(ArLog::Verbose, "ArSoundPlayer::playSoundPCM16[linux]: finished playing sound. (wrote %d bytes of 16-bit monaural signed sound data to /dev/dsp)", r);
00204   return true;
00205 }
00206 
00207 
00208 #endif  // ifdef WIN32
00209 

Generated on Wed Oct 19 12:56:37 2005 for Aria by  doxygen 1.4.0