virtual typename Source<T>::Range Read() override { auto r = buffer.Write(); if (!r.IsEmpty()) { unsigned n = Read(r.data, r.size); buffer.Append(n); } return buffer.Read(); }
virtual void DataReceived(const void *data, size_t length) { mutex.Lock(); auto range = buffer.Write(); if (range.length < length) length = range.length; memcpy(range.data, data, length); buffer.Append(length); mutex.Unlock(); SendNotification(); }
virtual typename Source<T>::Range read() { auto r = buffer.Write(); if (!r.IsEmpty()) { unsigned n = read(r.data, r.length); buffer.Append(n); } r = buffer.Read(); return typename Source<T>::Range(r.data, r.length); }
void BinaryReceived(const void *_data, size_t length) { const uint8_t *data = (const uint8_t *)_data, *end = data + length; do { /* append new data to buffer, as much as fits there */ auto range = binary_buffer.Write(); if (range.IsEmpty()) { /* overflow: reset buffer to recover quickly */ binary_buffer.Clear(); continue; } size_t nbytes = std::min(size_t(range.length), size_t(end - data)); memcpy(range.data, data, nbytes); data += nbytes; binary_buffer.Append(nbytes); while (true) { range = binary_buffer.Read(); if (range.IsEmpty()) break; size_t nbytes = HandleBinary(range.data, range.length); if (nbytes == 0) { if (binary_buffer.IsFull()) binary_buffer.Clear(); break; } binary_buffer.Consume(nbytes); } } while (data < end); }
bool Fill(TimeoutClock &timeout) { const auto dest = buffer.Write(); if (dest.IsEmpty()) /* already full */ return false; const Port::WaitResult wresult = port.WaitRead(env, timeout.GetRemainingOrZero()); if (wresult != Port::WaitResult::READY) return false; const int nbytes = port.Read(dest.data, dest.length); if (nbytes <= 0) return false; buffer.Append(nbytes); return true; }
virtual void OnNotification() { while (true) { char data[64]; size_t length; { ScopeLock protect(mutex); auto range = buffer.Read(); if (range.IsEmpty()) break; length = std::min(ARRAY_SIZE(data), size_t(range.length)); memcpy(data, range.data, length); buffer.Consume(length); } terminal.Write(data, length); } }
char *GetLine() { const auto src = buffer.Read(); char *const end = src.data + src.length; /* a NMEA line starts with a dollar symbol ... */ char *dollar = std::find(src.data, end, '$'); if (dollar == end) { buffer.Clear(); return nullptr; } char *start = dollar + 1; /* ... and ends with an asterisk */ char *asterisk = std::find(start, end, '*'); if (asterisk + 3 > end) /* need more data */ return nullptr; /* verify the checksum following the asterisk (two hex digits) */ const uint8_t calculated_checksum = NMEAChecksum(start, asterisk - start); const char checksum_buffer[3] = { asterisk[1], asterisk[2], 0 }; char *endptr; const uint8_t parsed_checksum = strtoul(checksum_buffer, &endptr, 16); if (endptr != checksum_buffer + 2 || parsed_checksum != calculated_checksum) { buffer.Clear(); return nullptr; } buffer.Consume(asterisk + 3 - src.data); *asterisk = 0; return start; }
void Flush() { port.Flush(); buffer.Clear(); }
virtual void consume(unsigned n) { buffer.Consume(n); position += n; }
// Mix data from each application stream and write result to the shared MMAP stream. void *AAudioServiceEndpointPlay::callbackLoop() { aaudio_result_t result = AAUDIO_OK; int64_t timeoutNanos = getStreamInternal()->calculateReasonableTimeout(); // result might be a frame count while (mCallbackEnabled.load() && getStreamInternal()->isActive() && (result >= 0)) { // Mix data from each active stream. mMixer.clear(); { // brackets are for lock_guard int index = 0; int64_t mmapFramesWritten = getStreamInternal()->getFramesWritten(); std::lock_guard <std::mutex> lock(mLockStreams); for (const auto clientStream : mRegisteredStreams) { int64_t clientFramesRead = 0; if (!clientStream->isRunning()) { continue; } sp<AAudioServiceStreamShared> streamShared = static_cast<AAudioServiceStreamShared *>(clientStream.get()); { // Lock the AudioFifo to protect against close. std::lock_guard <std::mutex> lock(streamShared->getAudioDataQueueLock()); FifoBuffer *fifo = streamShared->getAudioDataFifoBuffer_l(); if (fifo != nullptr) { // Determine offset between framePosition in client's stream // vs the underlying MMAP stream. clientFramesRead = fifo->getReadCounter(); // These two indices refer to the same frame. int64_t positionOffset = mmapFramesWritten - clientFramesRead; streamShared->setTimestampPositionOffset(positionOffset); float volume = 1.0; // to match legacy volume bool underflowed = mMixer.mix(index, fifo, volume); if (underflowed) { streamShared->incrementXRunCount(); } clientFramesRead = fifo->getReadCounter(); } } if (clientFramesRead > 0) { // This timestamp represents the completion of data being read out of the // client buffer. It is sent to the client and used in the timing model // to decide when the client has room to write more data. Timestamp timestamp(clientFramesRead, AudioClock::getNanoseconds()); streamShared->markTransferTime(timestamp); } index++; // just used for labelling tracks in systrace } } // Write mixer output to stream using a blocking write. result = getStreamInternal()->write(mMixer.getOutputBuffer(), getFramesPerBurst(), timeoutNanos); if (result == AAUDIO_ERROR_DISCONNECTED) { AAudioServiceEndpointShared::disconnectRegisteredStreams(); break; } else if (result != getFramesPerBurst()) { ALOGW("AAudioServiceEndpoint(): callbackLoop() wrote %d / %d", result, getFramesPerBurst()); break; } } return NULL; // TODO review }
void PFLAX() { binary = true; binary_buffer.Clear(); }
virtual void Consume(unsigned n) override { buffer.Consume(n); position += n; }
bool WesterboerVW921Device::DataReceived(const void *_data, size_t length, struct NMEAInfo &info) { assert(_data != NULL); assert(length > 0); bool result = false; const char *data = (const char *)_data, *end = data + length; do { // append new data to buffer, as much as fits there auto range = buffer.Write(); if (range.IsEmpty()) { // overflow: reset buffer to recover quickly buffer.Clear(); continue; } size_t nbytes = std::min(size_t(range.length), size_t(end - data)); memcpy(range.data, data, nbytes); data += nbytes; buffer.Append(nbytes); while (true) { // read data from the buffer, to see if there's a dollar character range = buffer.Read(); if (range.IsEmpty()) break; // Search for the dollar sign (sync byte) char *dollar = (char *)memchr(range.data, '$', range.length); if (dollar == NULL) // no dollar sign here: wait for more data break; // Make sure there are at least 5 bytes in the buffer to // read the sentence header unsigned remaining_length = range.length - (dollar - range.data); if (remaining_length < 5) break; // Check this is a Westerboer sentence if (dollar[1] != 'w') { // Skip this sentence buffer.Consume(dollar - range.data + 1); continue; } // Read the length of the sentence uint8_t sentence_length = (uint8_t)dollar[2]; // Check if the sentence was completely received already if (remaining_length < sentence_length) break; if (!CheckChecksum(dollar, sentence_length)) { // Skip this sentence buffer.Consume(dollar - range.data + 1); continue; } // Read the sentence identification number uint8_t sentence_number = (uint8_t)dollar[4]; // Parse the sentence SentenceReceived(sentence_number, dollar, sentence_length, info); buffer.Consume(dollar - range.data + sentence_length); result = true; } } while (data < end); return result; }