TEST_F(FSEventsTests, test_fsevents_run) { // Assume event type is registered. event_pub_ = std::make_shared<FSEventsEventPublisher>(); EventFactory::registerEventPublisher(event_pub_); // Create a subscriber. auto sub = std::make_shared<TestFSEventsEventSubscriber>(); EventFactory::registerEventSubscriber(sub); // Create a subscriptioning context auto mc = std::make_shared<FSEventsSubscriptionContext>(); mc->path = real_test_path; EventFactory::addSubscription( "fsevents", Subscription::create("TestFSEventsEventSubscriber", mc)); event_pub_->configure(); // Create an event loop thread (similar to main) temp_thread_ = std::thread(EventFactory::run, "fsevents"); EXPECT_TRUE(event_pub_->numEvents() == 0); // Wait for the thread to start and the FSEvents stream to turn on. WaitForStream(kMaxEventLatency); // Cause an fsevents event(s) by writing to the watched path. CreateEvents(); // Wait for the thread's run loop to select. WaitForEvents(kMaxEventLatency); EXPECT_TRUE(event_pub_->numEvents() > 0); // We are managing the thread ourselves, so no join needed. EventFactory::end(false); temp_thread_.join(); }
XnStatus XnDeviceBase::ReadStream(XnStreamData* pStreamOutput) { XnStatus nRetVal = XN_STATUS_OK; XN_VALIDATE_INPUT_PTR(pStreamOutput); if (m_ReadWriteMode.GetValue() == XN_DEVICE_MODE_WRITE) { return XN_STATUS_IO_DEVICE_WRONG_MODE; } // take the stream to read XnDeviceStream* pStream; nRetVal = FindStream(pStreamOutput->StreamName, &pStream); XN_IS_STATUS_OK(nRetVal); // make sure it is open if (!pStream->IsNewDataAvailable() && !pStream->IsOpen()) { return XN_STATUS_STREAM_NOT_OPEN; } // wait for it to advance nRetVal = WaitForStream(m_hNewDataEvent, pStream); XN_IS_STATUS_OK(nRetVal); // and read nRetVal = ReadFromStreamImpl(pStream, pStreamOutput); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); }
void CreateEvents(int num = 1) { WaitForStream(kMaxEventLatency); for (int i = 0; i < num; ++i) { FILE* fd = fopen(real_test_path.c_str(), "a"); fputs("fsevents", fd); fclose(fd); } }
bool PAPlayer::ProcessPAP() { /* * Here's what we should be doing in each player loop: * * 1. Run DoWork() on our audio device to actually output audio. * * 2. Pass our current buffer to the audio device to see if it wants anything, * and if so, reduce our buffer size accordingly. * * 3. Check whether we have space in our buffer for more data, and if so, * read some more in. * * 4. Check for end of file and return false if we reach it. * * 5. Perform any seeking and ffwd/rewding as necessary. * * 6. If we don't do anything in 2...5, we can take a breather and break out for sleeping. */ while (true) { if (m_bStop) return false; // Check for .cue sheet item end if (m_currentFile->m_lEndOffset && GetTime() >= GetTotalTime64()) { CLog::Log(LOGINFO, "PAPlayer: Passed end of track in a .cue sheet item"); m_decoder[m_currentDecoder].SetStatus(STATUS_ENDED); } // check whether we need to send off our callbacks etc. int status = m_decoder[m_currentDecoder].GetStatus(); if (status == STATUS_NO_FILE) return false; UpdateCacheLevel(); // check whether we should queue the next file up if ((GetTotalTime64() > 0) && GetTotalTime64() - GetTime() < TIME_TO_CACHE_NEXT_FILE + m_crossFading * 1000L && !m_cachingNextFile) { // request the next file from our application m_callback.OnQueueNextItem(); m_cachingNextFile = true; } if (m_crossFading && m_decoder[0].GetChannels() == m_decoder[1].GetChannels()) { if (((GetTotalTime64() - GetTime() < m_crossFading * 1000L) || (m_forceFadeToNext)) && !m_currentlyCrossFading) { // request the next file from our application if (m_decoder[1 - m_currentDecoder].GetStatus() == STATUS_QUEUED && m_pAudioDecoder[1 - m_currentStream]) { m_currentlyCrossFading = true; if (m_forceFadeToNext) { m_forceFadeToNext = false; m_crossFadeLength = m_crossFading * 1000L; } else { m_crossFadeLength = GetTotalTime64() - GetTime(); } m_currentDecoder = 1 - m_currentDecoder; m_decoder[m_currentDecoder].Start(); m_currentStream = 1 - m_currentStream; CLog::Log(LOGDEBUG, "Starting Crossfade - resuming stream %i", m_currentStream); m_pAudioDecoder[m_currentStream]->Resume(); m_callback.OnPlayBackStarted(); m_timeOffset = m_nextFile->m_lStartOffset * 1000 / 75; m_bytesSentOut = 0; *m_currentFile = *m_nextFile; m_nextFile->Reset(); m_cachingNextFile = false; } } } // Check for EOF and queue the next track if applicable if (m_decoder[m_currentDecoder].GetStatus() == STATUS_ENDED) { // time to swap tracks if (m_nextFile->m_strPath != m_currentFile->m_strPath || !m_nextFile->m_lStartOffset || m_nextFile->m_lStartOffset != m_currentFile->m_lEndOffset) { // don't have a .cue sheet item int nextstatus = m_decoder[1 - m_currentDecoder].GetStatus(); if (nextstatus == STATUS_QUEUED || nextstatus == STATUS_QUEUING || nextstatus == STATUS_PLAYING) { // swap streams CLog::Log(LOGDEBUG, "PAPlayer: Swapping tracks %i to %i", m_currentDecoder, 1-m_currentDecoder); if (!m_crossFading || m_decoder[0].GetChannels() != m_decoder[1].GetChannels()) { // playing gapless (we use only the 1 output stream in this case) int prefixAmount = m_decoder[m_currentDecoder].GetDataSize(); CLog::Log(LOGDEBUG, "PAPlayer::Prefixing %i samples of old data to new track for gapless playback", prefixAmount); m_decoder[1 - m_currentDecoder].PrefixData(m_decoder[m_currentDecoder].GetData(prefixAmount), prefixAmount); // check if we need to change the resampler (due to format change) unsigned int channels, samplerate, bitspersample; m_decoder[m_currentDecoder].GetDataFormat(&channels, &samplerate, &bitspersample); unsigned int channels2, samplerate2, bitspersample2; m_decoder[1 - m_currentDecoder].GetDataFormat(&channels2, &samplerate2, &bitspersample2); // change of channels - reinitialize our speaker configuration if (channels != channels2 || (g_advancedSettings.m_musicResample == 0 && (samplerate != samplerate2 || bitspersample != bitspersample2))) { CLog::Log(LOGINFO, "PAPlayer: Stream properties have changed, restarting stream"); FreeStream(m_currentStream); if (!CreateStream(m_currentStream, channels2, samplerate2, bitspersample2)) { CLog::Log(LOGERROR, "PAPlayer: Error creating stream!"); return false; } m_pAudioDecoder[m_currentStream]->Resume(); } else if (samplerate != samplerate2 || bitspersample != bitspersample2) { CLog::Log(LOGINFO, "PAPlayer: Restarting resampler due to a change in data format"); m_resampler[m_currentStream].DeInitialize(); if (!m_resampler[m_currentStream].InitConverter(samplerate2, bitspersample2, channels2, g_advancedSettings.m_musicResample, 16, PACKET_SIZE)) { CLog::Log(LOGERROR, "PAPlayer: Error initializing resampler!"); return false; } } CLog::Log(LOGINFO, "PAPlayer: Starting new track"); m_decoder[m_currentDecoder].Destroy(); m_decoder[1 - m_currentDecoder].Start(); m_callback.OnPlayBackStarted(); m_timeOffset = m_nextFile->m_lStartOffset * 1000 / 75; m_bytesSentOut = 0; *m_currentFile = *m_nextFile; m_nextFile->Reset(); m_cachingNextFile = false; m_currentDecoder = 1 - m_currentDecoder; } else { // cross fading - shouldn't ever get here - if we do, return false if (!m_currentlyCrossFading) { CLog::Log(LOGERROR, "End of file Reached before crossfading kicked in!"); return false; } else { CLog::Log(LOGINFO, "End of file reached before crossfading finished!"); return false; } } } else { if (GetTotalTime64() <= 0 && !m_bQueueFailed) { //we did not know the duration so didn't queue the next song, try queueing it now if (!m_cachingNextFile) {// request the next file from our application m_callback.OnQueueNextItem(); m_cachingNextFile = true; } } else { // no track queued - return and get another one once we are finished // with the current stream WaitForStream(); return false; } } } else { // set the next track playing (.cue sheet) m_decoder[m_currentDecoder].SetStatus(STATUS_PLAYING); m_callback.OnPlayBackStarted(); m_timeOffset = m_nextFile->m_lStartOffset * 1000 / 75; m_bytesSentOut = 0; *m_currentFile = *m_nextFile; m_nextFile->Reset(); m_cachingNextFile = false; } } // handle seeking and ffwd/rewding. HandleSeeking(); if (!HandleFFwdRewd()) { // need to skip to the next track - let's see if we already have another one m_decoder[m_currentDecoder].SetStatus(STATUS_ENDED); continue; // loop around to start the next track } if (!m_bPaused) { // Let our decoding stream(s) do their thing int retVal = m_decoder[m_currentDecoder].ReadSamples(PACKET_SIZE); if (retVal == RET_ERROR) { m_decoder[m_currentDecoder].Destroy(); return false; } int retVal2 = m_decoder[1 - m_currentDecoder].ReadSamples(PACKET_SIZE); if (retVal2 == RET_ERROR) { m_decoder[1 - m_currentDecoder].Destroy(); } // if we're cross-fading, then we do this for both streams, otherwise // we do it just for the one stream. if (m_currentlyCrossFading) { if (GetTime() >= m_crossFadeLength) // finished { CLog::Log(LOGDEBUG, "Finished Crossfading"); m_currentlyCrossFading = false; SetStreamVolume(m_currentStream, g_settings.m_nVolumeLevel); FreeStream(1 - m_currentStream); m_decoder[1 - m_currentDecoder].Destroy(); } else { float fraction = (float)(m_crossFadeLength - GetTime()) / (float)m_crossFadeLength - 0.5f; // make sure we can take valid logs. if (fraction > 0.499f) fraction = 0.499f; if (fraction < -0.499f) fraction = -0.499f; float volumeCurrent = 2000.0f * log10(0.5f - fraction); float volumeNext = 2000.0f * log10(0.5f + fraction); SetStreamVolume(m_currentStream, g_settings.m_nVolumeLevel + (int)volumeCurrent); SetStreamVolume(1 - m_currentStream, g_settings.m_nVolumeLevel + (int)volumeNext); if (AddPacketsToStream(1 - m_currentStream, m_decoder[1 - m_currentDecoder])) retVal2 = RET_SUCCESS; } } // add packets as necessary if (AddPacketsToStream(m_currentStream, m_decoder[m_currentDecoder])) retVal = RET_SUCCESS; if (retVal == RET_SLEEP && retVal2 == RET_SLEEP) { float maximumSleepTime = m_pAudioDecoder[m_currentStream]->GetCacheTime(); if (m_pAudioDecoder[1 - m_currentStream]) maximumSleepTime = std::min(maximumSleepTime, m_pAudioDecoder[1 - m_currentStream]->GetCacheTime()); int sleep = std::max((int)((maximumSleepTime / 2.0f) * 1000.0f), 1); Sleep(std::min(sleep, 15)); } } else Sleep(100); } return true; }