00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
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
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);
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
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
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
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
00174 int fd = open("/dev/dsp", O_WRONLY);
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
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