void System::onRawArrival( HANDLE handle ) { UINT pathLength = 0; if ( GetRawInputDeviceInfoW( handle, RIDI_DEVICENAME, NULL, &pathLength ) ) NIL_EXCEPT_WINAPI( "GetRawInputDeviceInfoW failed" ); wideString rawPath( pathLength, '\0' ); GetRawInputDeviceInfoW( handle, RIDI_DEVICENAME, &rawPath[0], &pathLength ); rawPath.resize( rawPath.length() - 1 ); for ( auto device : mDevices ) { if ( device->getHandler() != Device::Handler_RawInput ) continue; auto rawDevice = static_cast<RawInputDevice*>( device ); if ( !_wcsicmp( rawDevice->getRawPath().c_str(), rawPath.c_str() ) ) { deviceConnect( rawDevice ); return; } } auto device = new RawInputDevice( this, getNextID(), handle, rawPath ); if ( isInitializing() ) device->setStatus( Device::Status_Connected ); else deviceConnect( device ); mDevices.push_back( device ); }
BOOL CALLBACK System::diDeviceEnumCallback( LPCDIDEVICEINSTANCEW instance, LPVOID referer ) { auto system = reinterpret_cast<System*>( referer ); for ( auto identifier : system->mXInputDeviceIDs ) if ( instance->guidProduct.Data1 == identifier ) return DIENUM_CONTINUE; for ( auto device : system->mDevices ) { if ( device->getHandler() != Device::Handler_DirectInput ) continue; auto diDevice = static_cast<DirectInputDevice*>( device ); if ( diDevice->getInstanceID() == instance->guidInstance ) { if ( device->getSavedStatus() == Device::Status_Disconnected ) system->deviceConnect( device ); else device->setStatus( Device::Status_Connected ); return DIENUM_CONTINUE; } } Device* device = new DirectInputDevice( system, system->getNextID(), instance ); if ( system->isInitializing() ) device->setStatus( Device::Status_Connected ); else system->deviceConnect( device ); system->mDevices.push_back( device ); return DIENUM_CONTINUE; }
bool Stream::doInit(const char *url) { if(isInitializing()) { // this is not completely clean (should be within the lock) but otherwise the // caller would have to wait for the thread lock post("Still initializing %s/%s:%i",hostname.c_str(),mountpt.c_str(),port); return false; } bool ok = true; pthread_mutex_lock(&mutex); // close open file Reset(); // try to set host name, mount point, port number if(ok) { char *err = "Invalid URL"; try { ok = SetURL(url); } catch(char *tx) { err = tx; ok = false; } catch(...) { ok = false; } if(!ok) { post(err); ResetHost(); } } if(ok) { state = ST_INIT; pthread_cond_signal(&cond); } pthread_mutex_unlock(&mutex); // let the thread worker do the rest return ok; }
/*! Get sample frames \param buf pointer array to channel buffers \param frames number of maximum frames to get \return frames put into buffers */ int Stream::doGet(int ch,float *const *buf,int frames,float sr) { ASSERT(ch > 0 && frames >= 0 && sr > 0); if(isOk() && !isInitializing()) { // signal thread worker pthread_cond_signal(&cond); // check/(re)allocate buffers int strch = getChannels(); if(bufs && bufch < strch) { delete[] decoded; for(int i = 0; i < bufch; ++i) src_delete(src_state[i]); delete[] src_state; delete[] bufs; bufs = NULL; } if(!bufs) { if(bufch < strch) bufch = strch; bufs = new float *[bufch]; decoded = new Fifo<float>[bufch]; src_state = new SRC_STATE *[bufch]; for(int i = 0; i < bufch; ++i) { int error; src_state[i] = src_new(SRC_ZERO_ORDER_HOLD,1,&error); if(!src_state[i]) post("src init error %i",error); } } // get frames float ratio = sr/getSamplerate(); int frneed = (int)(frames/ratio)+DECMORE; // number of frames to read from decoder fifo if(decoded[0].Size() < frneed) { // fifos are too small -> resize them (while keeping their contents) for(int i = 0; i < bufch; ++i) decoded[i].Resize(frneed,true); } // how many frames do we need to get from decoder? int frread = frneed-decoded[0].Have(); int ret = state == ST_WAIT?0:DataRead(frread); if(ret < 0) { if(debug) post("read error"); // clear output for(int c = 0; c < ch; ++c) memset(buf[c],0,frames*sizeof *buf[c]); return 0; } else { // how many channels do we really need for output? // this should be set elsewhere, because we can't change anyway!!! // (SRC_STATE for dangling channels would be incorrect) int cmin = strch; if(ch < cmin) cmin = ch; // write data to fifo for(int i = 0; i < cmin; ++i) { int wr = decoded[i].Write(ret,bufs[i]); if(wr < ret) post("fifo overflow"); } // state = ST_PROCESS; if(ratio == 1) { // no resampling necessary // hopefully all channel fifos advance uniformly..... for(int i = 0; i < cmin; ++i) { for(int got = 0; got < frames; ) { int cnt = frames-got; if(decoded[i].Have()) { got += decoded[i].Read(cnt,buf[i]+got); } else { state = ST_WAIT; if(debug) post("fifo underrun"); // Buffer underrun!! -> zero output buffer memset(buf[i]+got,0,cnt*sizeof(*buf[i])); got += cnt; } } } } else { SRC_DATA src_data; src_data.src_ratio = ratio; src_data.end_of_input = 0; // hopefully all channel fifos advance uniformly..... for(int i = 0; i < cmin; ++i) { src_set_ratio(src_state[i],ratio); for(int got = 0; got < frames; ) { src_data.data_out = buf[i]+got; src_data.output_frames = frames-got; if(decoded[i].Have()) { src_data.data_in = decoded[i].ReadPtr(); src_data.input_frames = decoded[i].ReadSamples(); int err = src_process(src_state[i],&src_data); if(err) post("src_process error %i",err); // advance buffer decoded[i].Read(src_data.input_frames_used,NULL); } else { state = ST_WAIT; if(debug) post("fifo underrun"); // Buffer underrun!! -> zero output buffer memset(src_data.data_out,0,src_data.output_frames*sizeof(*src_data.data_out)); src_data.output_frames_gen = src_data.output_frames; } got += src_data.output_frames_gen; } } } // zero remaining channels for(int c = cmin; c < ch; ++c) memset(buf[c],0,frames*sizeof *buf[c]); return ret; } } else { for(int c = 0; c < ch; ++c) memset(buf[c],0,frames*sizeof *buf[c]); return 0; } }