diff options
Diffstat (limited to 'flow/audiosubsys.h')
-rw-r--r-- | flow/audiosubsys.h | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/flow/audiosubsys.h b/flow/audiosubsys.h new file mode 100644 index 0000000..ede38c2 --- /dev/null +++ b/flow/audiosubsys.h @@ -0,0 +1,236 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef AUDIOSUBSYS_H +#define AUDIOSUBSYS_H +#include <string> + +#include "arts_export.h" +#include "pipebuffer.h" +#include "startupmanager.h" + +/* + * BC - Status (2002-03-08): AudioSubSystem, ASProducer, ASConsumer. + * + * These classes are kept binary compatible. You can rely on them. + * AudioSubSystem has a private data pointer to do so. Even if ports to + * other architectures or hardware will require different organization + * (i.e. no fragments, direct memory access via mmap), the data members + * and functions exported here MAY NOT BE CHANGED. Use the private data + * pointer for adding data members. + * + * If ASProducer/ASConsumer doesn't suit the needs any longer, do NOT + * change them. Add new classes instead. + */ + +namespace Arts { + +class ASProducer { +public: + virtual void needMore() = 0; +}; + +// FIXME: haveMore won't be called currently +class ASConsumer { +public: + virtual void haveMore() = 0; +}; + +class ARTS_EXPORT AudioSubSystemStart :public StartupClass { +protected: + class AudioSubSystem *_instance; +public: + inline AudioSubSystem *the() { return _instance; }; + void startup(); + void shutdown(); +}; + +class AudioSubSystemPrivate; + +class ARTS_EXPORT AudioSubSystem { + class AudioSubSystemPrivate *d; + + std::string _error; + char *fragment_buffer; + + int _fragmentCount; + int _fragmentSize; + + bool _running; + PipeBuffer wBuffer, rBuffer; + ASConsumer *consumer; + ASProducer *producer; + + friend class AudioSubSystemStart; + AudioSubSystem(); + ~AudioSubSystem(); + + void close(); + void initAudioIO(); + + /** + * checks that full duplex doesn't go out of sync + */ + void adjustDuplexBuffers(); + + /** + * creates count empty fragments of input in rBuffer if count > 0 + * removes count fragments of input from rBuffer if count < 0 + */ + void adjustInputBuffer(int count); + +public: + enum { ioRead=1, ioWrite=2, ioExcept=4 }; + + // singleton + static AudioSubSystem *the(); + + /* + * Currently, if you want to use the AudioSubSystem, you need to + * + * 1. - attach one producer + * - attach one consumer (only for full duplex) + * - open the audio subsystem using open (watch the fd) + * (in any order) + * + * 2. react on the callbacks you get for the producer + * + * 3. if you don't need the audio subsystem any longer, call detach + * both, the producer and the cosumer. + * + * Be careful that you don't read/write from/to the audio subsystem + * when running() is not true. + */ + + bool attachProducer(ASProducer *producer); + bool attachConsumer(ASConsumer *consumer); + + void detachProducer(); + void detachConsumer(); + + /* + * can be used to select the AudioIO class to use, reasonable choices + * may be "oss" or "alsa" at this point in time - you need to choose + * this before doing anything else + */ + void audioIO(const std::string& audioIO); + std::string audioIO(); + + // which device to use for audio output (default /dev/dsp) + void deviceName(const std::string& deviceName); + std::string deviceName(); + + void fragmentSize(int size); + int fragmentSize(); + + void fragmentCount(int fragments); + int fragmentCount(); + + void samplingRate(int samplingrate); + int samplingRate(); + + void channels(int channels); + int channels(); + + void format(int format); + int format(); + + /** + * As opposed to format(), this one returns the number of bits used per + * sample. Thats sometimes a difference, for instance 16bit big endian + * encoding has the format() 17, whereas bits() would return 16. + */ + int bits(); + + void fullDuplex(bool newFullDuplex); + bool fullDuplex(); + + bool check(); + + /** + * Opens the audio device. + * + * After opening, you must check selectReadFD() and selectWriteFD() to + * select() on the appropriate file descriptors. Whenever select()ing is + * successful, handleIO needs to be called. + * + * The type for handleIO must be set to ioRead if fd is ready for + * reading, ioWrite if fd is ready for writing, ioExcept if something + * special happend or any combination of these using bitwise or. + * + * @returns true if audio device has been opened successfully, + * false otherwise + */ + bool open(); + + /** + * human readable error message that descibes why opening the audio device + * failed + */ + const char *error(); + + /** + * File descriptor to select on for reading (@see open()), -1 if there is + * none. + */ + int selectReadFD(); + + /** + * File descriptor to select on for writing (@see open()), -1 if there is + * none. + */ + int selectWriteFD(); + + /** + * Needs to be called to handle I/O on the filedescriptors given by + * selectReadFD() and selectWriteFD() (@see open()). + */ + void handleIO(int type); + + void read(void *buffer, int size); + void write(void *buffer, int size); + + /** + * this returns the time in seconds it will take until everything written + * to the AudioSubSystem so far will be played - in other words, it returns + * the time it will take until the next sample written by the application + * will be heard by the user + */ + float outputDelay(); + + /** + * returns true as long as the audio subsystem is opened and active (that + * is, between successful opening, with attaching producer, and the first + * detachConsumer/detachProducer) + */ + bool running(); + + /** + * called during crashes, to release the opened device (and other resources) + * don't use this method for other purposes than emergencies + */ + void emergencyCleanup(); +}; + +} + +#endif /* AUDIOSUBSYS_H */ |