00001
00002 #include "PANetworkPlayer.hxx"
00003 #include "PushFlowControl.hxx"
00004
00005 #include "AudioSink.hxx"
00006 #include "AudioSource.hxx"
00007
00008 #include <pthread.h>
00009
00010
00011 namespace CLAM
00012 {
00013
00014
00015 int PANetworkPlayer::ProcessCallback (
00016 const void *inputBuffers,
00017 void *outputBuffers,
00018 unsigned long framesPerBuffer,
00019 const PaStreamCallbackTimeInfo* timeInfo,
00020 PaStreamCallbackFlags statusFlags,
00021 void *userData
00022 )
00023 {
00024 if (statusFlags)
00025 {
00026 if (statusFlags & paOutputUnderflow)
00027 std::cerr << "Portaudio backend: Output Underflow" << std::endl;
00028 if (statusFlags & paInputUnderflow)
00029 std::cerr << "Portaudio backend: Input Underflow" << std::endl;
00030 if (statusFlags & paOutputOverflow)
00031 std::cerr << "Portaudio backend: Output Overflow" << std::endl;
00032 if (statusFlags & paInputOverflow)
00033 std::cerr << "Portaudio backend: Input Overflow" << std::endl;
00034 if (statusFlags & paPrimingOutput)
00035 std::cerr << "Portaudio backend: Priming Output" << std::endl;
00036 }
00037 PANetworkPlayer* player=(PANetworkPlayer*)userData;
00038
00039 player->Do(inputBuffers, outputBuffers, framesPerBuffer);
00040
00041 return 0;
00042 }
00043
00044 namespace {
00045
00046 void displayPADevices()
00047 {
00048 int howManiApis = Pa_GetHostApiCount();
00049 int defaultApi = Pa_GetDefaultHostApi();
00050 std::cout << "Default API " << defaultApi << std::endl;
00051 for (int api=0; api<howManiApis; api++)
00052 {
00053 const PaHostApiInfo * apiInfo = Pa_GetHostApiInfo( api );
00054 std::cout
00055 << (api==defaultApi?"* ":" ")
00056 << apiInfo->name
00057 << " (" << api << ")"
00058 << std::endl;
00059 for (int device=0; device<apiInfo->deviceCount; device++)
00060 {
00061 int fullDevice = Pa_HostApiDeviceIndexToDeviceIndex(api, device);
00062 const PaDeviceInfo * deviceInfo = Pa_GetDeviceInfo(fullDevice);
00063 std::cout << "\t"
00064 << " (" << fullDevice << "/" << device << ") "
00065 << (fullDevice == Pa_GetDefaultInputDevice()? "*<": " ")
00066 << (fullDevice == Pa_GetDefaultOutputDevice()? "*>": " ")
00067 << (fullDevice == apiInfo->defaultInputDevice?"*<":" ")
00068 << (fullDevice == apiInfo->defaultOutputDevice?"*>":" ")
00069 << deviceInfo->name
00070 << " Inputs: " << deviceInfo->maxInputChannels
00071 << " Outputs: " << deviceInfo->maxOutputChannels
00072 << std::endl;
00073 }
00074 }
00075 }
00076
00077 }
00078
00079 PANetworkPlayer::PANetworkPlayer()
00080 : mPreferredBufferSize(paFramesPerBufferUnspecified)
00081 , mSamplingRate(44100)
00082 , mPortAudioStream(0)
00083 , mError(paNoError)
00084 {
00085 }
00086
00087 PANetworkPlayer::~PANetworkPlayer()
00088 {
00089 Stop();
00090 }
00091
00092 void PANetworkPlayer::Start()
00093 {
00094 if (IsPlaying()) return;
00095 if (IsPaused())
00096 {
00097 BePlaying();
00098 return;
00099 }
00100 if (CheckPaError(Pa_Initialize())) return;
00101 displayPADevices();
00102
00103 CacheSourcesAndSinks();
00104
00105 int nInChannels = GetNSources();
00106 int nOutChannels = GetNSinks();
00107
00108 PaHostApiTypeId apiTryList[] = {
00109 paDirectSound,
00110 paMME,
00111 paASIO,
00112 paSoundManager,
00113 paCoreAudio,
00114 paALSA,
00115 paAL,
00116 paBeOS,
00117 paWDMKS,
00118 paJACK,
00119
00120
00121 paOSS,
00122 paInDevelopment
00123 };
00124
00125
00126
00127 const PaHostApiInfo * apiInfo = 0;
00128 for (unsigned i=0; apiTryList[i]!=paInDevelopment; i++)
00129 {
00130 PaHostApiIndex apiIndex = Pa_HostApiTypeIdToHostApiIndex(apiTryList[i]);
00131 std::cerr << apiIndex << std::endl;
00132 if (apiIndex<0) continue;
00133 apiInfo = Pa_GetHostApiInfo( apiIndex );
00134 std::cerr << "Portaudio Chosen API: " << apiInfo->name << " " << apiIndex << std::endl;
00135 break;
00136 }
00137 CLAM_ASSERT(apiInfo, "PortAudio: No API available.");
00138
00139
00140 PaStreamParameters inputParameters;
00141 PaStreamParameters * inParams = 0;
00142 if (nInChannels)
00143 {
00144 inputParameters.device = apiInfo->defaultInputDevice;
00145 if ( inputParameters.device == paNoDevice )
00146 {
00147 mErrorMessage = "No free default input device";
00148 std::cerr << "PortAudio Error: " << mErrorMessage << std::endl;
00149 return;
00150 }
00151 const PaDeviceInfo * info = Pa_GetDeviceInfo( inputParameters.device );
00152 std::cerr << "PortAudio: Chosen Input: " << info->name << std::endl;
00153 if (nInChannels > Pa_GetDeviceInfo( inputParameters.device )->maxInputChannels)
00154 {
00155 mErrorMessage = "Too many input channels for the default device";
00156 std::cerr << "PortAudio Error: " << mErrorMessage << std::endl;
00157 return;
00158 }
00159 inputParameters.channelCount = nInChannels;
00160 inputParameters.sampleFormat = paFloat32 | paNonInterleaved ;
00161 inputParameters.suggestedLatency = info->defaultLowOutputLatency;
00162 inputParameters.hostApiSpecificStreamInfo = NULL;
00163 inParams = &inputParameters;
00164 }
00165
00166 PaStreamParameters outputParameters;
00167 PaStreamParameters * outParams = 0;
00168 if (nOutChannels)
00169 {
00170 outputParameters.device = apiInfo->defaultOutputDevice;
00171 if ( outputParameters.device == paNoDevice )
00172 {
00173 mErrorMessage = "No free default output device";
00174 std::cerr << "PortAudio Error: " << mErrorMessage << std::endl;
00175 return;
00176 }
00177 const PaDeviceInfo * info = Pa_GetDeviceInfo( outputParameters.device );
00178 std::cerr << "PortAudio: Chosen Output: " << info->name << std::endl;
00179 if (nOutChannels > Pa_GetDeviceInfo( outputParameters.device )->maxOutputChannels)
00180 {
00181 mErrorMessage = "Too many output channels for the default device";
00182 std::cerr << "PortAudio Error: " << mErrorMessage << std::endl;
00183 return;
00184 }
00185 outputParameters.channelCount = nOutChannels;
00186 outputParameters.sampleFormat = paFloat32 | paNonInterleaved ;
00187 outputParameters.suggestedLatency = info->defaultLowOutputLatency;
00188 outputParameters.hostApiSpecificStreamInfo = NULL;
00189 outParams = &outputParameters;
00190 }
00191
00192 CLAM_ASSERT(!mPortAudioStream, "Portaudio: Previous stream not closed");
00193 if (CheckPaError(
00194 Pa_OpenStream(
00195 &mPortAudioStream,
00196 inParams,
00197 outParams,
00198 double(mSamplingRate),
00199 mPreferredBufferSize,
00200 paClipOff,
00201 ProcessCallback,
00202 this )
00203 ))
00204 {
00205 mErrorMessage = "Audio i/o devices requirements not fullfilled";
00206 return;
00207 }
00208
00209 BePlaying();
00210 const PaStreamInfo * streamInfo = Pa_GetStreamInfo(mPortAudioStream);
00211 std::cout << "Sample rate: " << streamInfo->sampleRate << std::endl;
00212 std::cout << "Input latency: " << streamInfo->inputLatency << std::endl;
00213 std::cout << "Output latency: " << streamInfo->outputLatency << std::endl;
00214
00215 mNeedsPriority=true;
00216 Pa_StartStream( mPortAudioStream );
00217 }
00218
00219 void PANetworkPlayer::Stop()
00220 {
00221 if (IsStopped()) return;
00222 if ( mPortAudioStream )
00223 {
00224 Pa_StopStream( mPortAudioStream );
00225 CheckPaError( Pa_CloseStream( mPortAudioStream ) );
00226 mPortAudioStream=0;
00227 }
00228 BeStopped();
00229 Pa_Terminate();
00230 }
00231
00232 bool PANetworkPlayer::IsWorking()
00233 {
00234 return mError==paNoError;
00235 }
00236
00237 std::string PANetworkPlayer::NonWorkingReason()
00238 {
00239 return mErrorMessage;
00240 }
00241
00242 bool PANetworkPlayer::CheckPaError(PaError result)
00243 {
00244 mError = result;
00245 if( result == paNoError ) return false;
00246 mErrorMessage = Pa_GetErrorText(mError);
00247 std::cerr
00248 << "PortAudio Error #" << result << ": "
00249 << Pa_GetErrorText( result ) << std::endl;
00250 return true;
00251 }
00252
00253 void PANetworkPlayer::Do(const void *inputBuffers, void *outputBuffers,
00254 unsigned long framesPerBuffer)
00255 {
00256 if (IsStopped()) return;
00257 if (mNeedsPriority)
00258 {
00259 mNeedsPriority = false;
00260 #ifdef TODO__was_WIN32
00261 BOOL res;
00262 DWORD err;
00263
00264 res = SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS );
00265 err = GetLastError();
00266 res = SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL );
00267 err = GetLastError();
00268 #else
00269 struct sched_param sched_param;
00270 int policy;
00271
00272 if (pthread_getschedparam(pthread_self(), &policy, &sched_param) < 0)
00273 std::cerr << "Scheduler getparam failed..." << std::endl;
00274 sched_param.sched_priority = sched_get_priority_max(SCHED_RR)-1;
00275 if (!pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param))
00276 std::cerr << "Scheduler set to Round Robin with priority "<< sched_param.sched_priority << std::endl;
00277 #endif
00278 }
00279 if (IsPaused())
00280 {
00281 MuteOutBuffers((float**) outputBuffers, framesPerBuffer);
00282 return;
00283 }
00284 DoInPorts( (float**) inputBuffers, framesPerBuffer);
00285 DoOutPorts( (float**) outputBuffers, framesPerBuffer);
00286 GetNetwork().Do();
00287 }
00288
00289 void PANetworkPlayer::DoInPorts(float** input, unsigned long nframes)
00290 {
00291 for(unsigned i = 0; i < GetNSources(); ++i)
00292 {
00293 SetSourceBuffer(i, input[i], nframes);
00294 }
00295 }
00296
00297 void PANetworkPlayer::DoOutPorts(float** output, unsigned long nframes)
00298 {
00299 for (unsigned i=0; i<GetNSinks(); ++i)
00300 {
00301 SetSinkBuffer(i, output[i], nframes);
00302 }
00303 }
00304
00305 void PANetworkPlayer::MuteOutBuffers(float** output, unsigned long nframes)
00306 {
00307 unsigned nSinks = GetNSinks();
00308 for (unsigned i=0; i<nSinks; i++)
00309 std::memset(output[i], 0, nframes*sizeof(float));
00310 }
00311
00312 }
00313