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 #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
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
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
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
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);
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
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
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
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
00176 int fd = open("/dev/dsp", O_WRONLY);
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
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