/* * BC - tqStatus (2002-03-08): ByteBuffer, BufferQueue * * None of these classes is considered part of the public API. Do NOT use it * in your apps. These are part of the implementation of libartsflow's * AudioSubSystem, and subject to change/disappearing due to optimization * work. */ #ifndef _BUFFERQUEUE_H #define _BUFFERQUEUE_H #include "thread.h" #define _DEFAULT_CHUNK_SIZE 4096 #define _MAX_CHUNKS 3 namespace Arts { class ByteBuffer { unsigned char* content; int _size; int _maxSize; int rp; public: ByteBuffer() { _size = rp = 0; _maxSize = _DEFAULT_CHUNK_SIZE; content = new unsigned char[_DEFAULT_CHUNK_SIZE]; } ByteBuffer(const void* s, int len) { _maxSize = _DEFAULT_CHUNK_SIZE; content = new unsigned char[_DEFAULT_CHUNK_SIZE]; put(s, len); } ~ByteBuffer() { delete [] content; } void put(const void* s, int len) { if ((_size = len) != 0) memcpy(content, s, len); rp = 0; } void* get() { return content+rp; } void* reset() { _size = 0; rp = 0; return content; } int push(int len) { _size -= len; rp += len; return _size; } void set(int len) { _size = len; rp = 0; } int size() const { return _size; } int maxSize() const { return _maxSize; } void setMaxSize(int size) { delete [] content; content = new unsigned char[size]; _maxSize = size; } }; /////////////////////////////////////////////////////////////////////////////// class BufferQueue { private: ByteBuffer bufs[_MAX_CHUNKS]; int rp; int wp; Arts::Semaphore* sema_produced; Arts::Semaphore* sema_consumed; void semaReinit() { delete sema_consumed; delete sema_produced; sema_consumed = new Arts::Semaphore(0, _MAX_CHUNKS); sema_produced = new Arts::Semaphore(0, 0); } public: BufferQueue() { rp = wp = 0; sema_consumed = new Arts::Semaphore(0, _MAX_CHUNKS); sema_produced = new Arts::Semaphore(0, 0); } ~BufferQueue() { delete sema_consumed; delete sema_produced; } void write(void* data, int len); ByteBuffer* waitConsumed(); void produced(); ByteBuffer* waitProduced(); void consumed(); bool isEmpty() const { return sema_produced->getValue() == 0; } int bufferedChunks() const { return sema_produced->getValue(); } int freeChunks() const { return sema_consumed->getValue(); } int maxChunks() const { return _MAX_CHUNKS; } int chunkSize() const { return bufs[0].maxSize(); } void clear() { rp = wp = 0; semaReinit(); } void setChunkSize(int size){ for (int i=0; i < maxChunks(); i++) bufs[i].setMaxSize(size); } }; /////////////////////////////////////////////////////////////////////////////// inline void BufferQueue::write(void* data, int len) { sema_consumed->wait(); bufs[wp].put(data, len); ++wp %= _MAX_CHUNKS; sema_produced->post(); } inline ByteBuffer* BufferQueue::waitConsumed() { sema_consumed->wait(); return &bufs[wp]; } inline void BufferQueue::produced() { ++wp %= _MAX_CHUNKS; sema_produced->post(); } inline ByteBuffer* BufferQueue::waitProduced() { sema_produced->wait(); return &bufs[rp]; } inline void BufferQueue::consumed() { ++rp %=_MAX_CHUNKS; sema_consumed->post(); } } #endif