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

ArSoundPlayer.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
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 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 
00027 #include "ArExport.h"
00028 #include "ArSoundPlayer.h"
00029 #include "Aria.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 
00037 AREXPORT ArRetFunctor2<bool, const char*, const char*>* ArSoundPlayer::getPlayWavFileCallback() 
00038 {
00039   return &ourPlayWavFileCB;
00040 }
00041 
00042 
00043 AREXPORT ArFunctor* ArSoundPlayer::getStopPlayingCallback()
00044 {
00045   return &ourStopPlayingCB;
00046 }
00047 
00048 
00049 #ifdef WIN32
00050 
00051       /* Windows: */
00052 
00053 #include <assert.h>
00054 
00055 AREXPORT bool ArSoundPlayer::playWavFile(const char* filename, const char* params) 
00056 {
00057   return (PlaySound(filename, NULL, SND_FILENAME) == TRUE);
00058 }
00059 
00060 AREXPORT bool ArSoundPlayer::playNativeFile(const char* filename, const char* params)
00061 {
00062   /* WAV is the Windows native format */
00063   return playWavFile(filename, 0);
00064 }
00065 
00066 AREXPORT void ArSoundPlayer::stopPlaying()
00067 {
00068   PlaySound(NULL, NULL, NULL);
00069 }
00070 
00071 
00072 AREXPORT bool ArSoundPlayer::playSoundPCM16(char* data, int numSamples)
00073 {
00074   ArLog::log(ArLog::Terse, "INTERNAL ERROR: ArSoundPlayer::playSoundPCM16() is not implemented for Windows yet! Bug reed@activmedia.com about it!");
00075   assert(false);
00076 
00077   return false;
00078 }
00079 
00080 #else
00081 
00082       /* Linux: */
00083 
00084 #include <stdio.h>
00085 #include <sys/ioctl.h>
00086 #include <sys/types.h>
00087 #include <sys/stat.h>
00088 #include <sys/wait.h>
00089 #include <fcntl.h>
00090 #include <sys/soundcard.h>
00091 //#include <linux/soundcard.h>
00092 #include <unistd.h>
00093 #include <errno.h>
00094 
00095 
00096 
00097 bool ArSoundPlayer::playNativeFile(const char* filename, const char* params)
00098 {
00099   int snd_fd = open("/dev/dsp", O_WRONLY); // | O_NONBLOCK);
00100   if(snd_fd < 0) {
00101     return false;
00102   }
00103   int file_fd = open(filename, O_RDONLY);
00104   if(file_fd < 0)
00105   {
00106     perror("ArSoundPlayer::playNativeFile");
00107     return false;
00108   }
00109   int len;
00110   const int buflen = 512;
00111   char buf[buflen];
00112   while((len = read(file_fd, buf, buflen)) > 0)
00113   {
00114     if (write(snd_fd, buf, len) != len) {
00115       perror("ArSoundPlayer::playNativeFile");
00116     }
00117   }
00118   close(file_fd);
00119   close(snd_fd);
00120   return true;
00121 }
00122 
00123 bool ArSoundPlayer::playWavFile(const char* filename, const char* params)
00124 {
00125   char* prog = NULL;
00126   prog = getenv("PLAY_WAV");
00127   if(prog == NULL)
00128     prog = "play";
00129   myPlayChildPID = fork();
00130   if(myPlayChildPID == -1) 
00131   {
00132     ArLog::log(ArLog::Terse, "ArSoundPlayer: error forking!");
00133     perror("Aria: ArSoundPlayer");
00134     return false;
00135   }
00136   if(myPlayChildPID == 0)
00137   {
00138     // child process: execute sox
00139     ArLog::log(ArLog::Verbose, "ArSoundPlayer: executing \"%s\" with argument \"%s\" in child process...\n", prog, filename);
00140     if(execlp(prog, prog, filename, (char*)0) < 0) 
00141     {
00142       perror("Aria: ArSoundPlayer: Error executing Wav file playback program");
00143       exit(-1);
00144     }
00145   } 
00146   // parent process: wait for child to finish
00147   ArLog::log(ArLog::Verbose, "ArSoundPlayer: created child process %d to play wav file \"%s\".", 
00148       myPlayChildPID, filename);
00149   int status;
00150   waitpid(myPlayChildPID, &status, 0);
00151   if(WEXITSTATUS(status) != 0) {
00152     ArLog::log(ArLog::Terse, "ArSoundPlayer: Error: Wav file playback program \"%s\" exited with error code %d.", prog, WEXITSTATUS(status));
00153     myPlayChildPID = -1;
00154     return false;
00155   }
00156   myPlayChildPID = -1;
00157   return true;
00158 }
00159 
00160 
00161 
00162 void ArSoundPlayer::stopPlaying()
00163 {
00164   // Kill a child processes (created by playWavFile) if it exists.
00165   if(myPlayChildPID > 0)
00166   {
00167     ArLog::log(ArLog::Verbose, "ArSoundPlayer: Sending SIGTERM to child process %d.", myPlayChildPID);
00168     kill(myPlayChildPID, SIGTERM);
00169   }
00170 }
00171 
00172 
00173 bool ArSoundPlayer::playSoundPCM16(char* data, int numSamples)
00174 {
00175   //ArLog::log(ArLog::Normal, "ArSoundPlayer::playSoundPCM16[linux]: opening sound device.");
00176   int fd = open("/dev/dsp", O_WRONLY); // | O_NONBLOCK);
00177   if(fd < 0)
00178     return false;
00179   int arg = AFMT_S16_LE;
00180   if(ioctl(fd, SNDCTL_DSP_SETFMT, &arg) != 0)
00181   {
00182     close(fd);
00183     return false;
00184   }
00185   arg = 0;
00186   if(ioctl(fd, SNDCTL_DSP_STEREO, &arg) != 0)
00187   {
00188     close(fd);
00189     return false;
00190   }
00191   arg = 16000;
00192   if(ioctl(fd, SNDCTL_DSP_SPEED, &arg) != 0)
00193   {
00194     close(fd);
00195     return false;
00196   }
00197   //ArLog::log(ArLog::Normal, "ArSoundPlayer::playSoundPCM16[linux]: writing %d bytes to sound device.", 2*numSamples);
00198   int r;
00199   if((r = write(fd, data, 2*numSamples) < 0))
00200   {
00201     close(fd);
00202     return false;
00203   }
00204   close(fd);
00205   ArLog::log(ArLog::Verbose, "ArSoundPlayer::playSoundPCM16[linux]: finished playing sound. (wrote %d bytes of 16-bit monaural signed sound data to /dev/dsp)", r);
00206   return true;
00207 }
00208 
00209 
00210 
00211 #endif  // ifdef WIN32
00212 

Generated on Tue Feb 20 10:51:41 2007 for Aria by  doxygen 1.4.0