/*  This file is part of the KDE project
    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#ifndef PHONON_PCMIODEVICE_H
#define PHONON_PCMIODEVICE_H

#include <QtCore/QIODevice>
#include <Phonon/Global>
#include <Phonon/AudioOutputDevice>

namespace Phonon
{

/*
 * Basic idea: make a PcmIODevice class that is a subclass of QIODevice and resembles
 * QAbstractSocket
 *
 * The open function takes
 * - a Phonon::Category
 * - a list of formats
 * - flags ReadOnly/WriteOnly/FixedFormat
 *
 * A signal is emitted when the format changes - the app has to handle the format change, except if
 * it specified FixedFormat, then the backend has to do the format conversion if necessary.
 *
 * Provide Packet and PacketPool classes for a convenient way to manage the memory of buffers.
 */

class PcmIODevicePrivate;
class PcmIODevice : public QIODevice
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(PcmIODevice)
    public:
        explicit PcmIODevice(QObject *parent = 0);
        ~PcmIODevice();

        void setOutputDevice(const Phonon::AudioOutputDevice &outDevice);
        //void setCaptureDevice(const Phonon::AudioCaptureDevice &inDevice);
        AudioOutputDevice outputDevice() const;
        //AudioCaptureDevice captureDevice() const;

        void setCategory(Phonon::Category cat);
        Phonon::Category category() const;

        enum BitRate {
            UnknownBitRate = -1,
            /**
             * Audio Data is transported as values from -128 to 127.
             */
            Signed8Bit,
            /**
             * Audio Data is transported as values from 0 to 255
             */
            Unsigned8Bit,
            /**
             * Audio Data is transported as values from -2^15 to 2^15-1
             */
            Signed16Bit,
            Signed18Bit,
            Signed20Bit,
            /**
             * Audio Data is transported as values from -2^23 to 2^23-1. The data is packed in 3
             * Bytes and not padded with a 0 Byte.
             */
            Signed24Bit,
            /**
             * Audio Data is transported as values from -2^31 to 2^31-1
             */
            Signed32Bit
        };

        void setFormat(int sampleRate, BitRate bitRate = Signed16Bit, int channels = 2, QSysInfo::Endian byteOrder = QSysInfo::ByteOrder);
        void addFormat(int sampleRate, BitRate bitRate = Signed16Bit, int channels = 2, QSysInfo::Endian byteOrder = QSysInfo::ByteOrder);

        int sampleRate() const;
        BitRate bitRate() const;
        int channels() const;
        QSysInfo::Endian byteOrder() const;

        /**
         */
        enum PcmIOModeFlags {
            Relaxed = 0,
            /**
             * Will use the smallest buffers possible in order to achieve minimal latency
             * between the soundcard and your application.
             */
            LowLatency = 1,
            /**
             * Using this flag the format will be decided on open and never change. The format could
             * change if hardware is unplugged and a fallback is used or hardware is plugged in and
             * is a preferred device. In that event, when using FixedFormat, %Phonon will do the
             * format conversion for you.
             */
            FixedFormat = 2
        };
        typedef QFlags<PcmIOModeFlags> PcmIOMode;
        PcmIOMode mode() const;

        void setReadyReadThreshold(int milliseconds);

        /**
         * Reimplemented for internal reasons
         */
        virtual bool open(QIODevice::OpenMode openMode);

        /**
         * QIODevice::Append, QIODevice::Truncate, QIODevice::Text, QIODevice::Unbuffered are
         * ignored
         */
        bool open(QIODevice::OpenMode openMode, PcmIOMode hints);

        virtual void close();

    protected:
        virtual qint64 readData(char *data, qint64 maxSize);
        virtual qint64 writeData(const char *data, qint64 maxSize);

        PcmIODevicePrivate *const d_ptr;
};

} // namespace Phonon

//Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::PcmIODevice::PcmIOModes)

#endif // PHONON_PCMIODEVICE_H
