//
// PT3Tuner.h
//

#ifndef __RY0_DEVICE_PT3_PT3TUNER_H__
#define __RY0_DEVICE_PT3_PT3TUNER_H__

#include <stdint.h>
#include "ry0/device/Tuner.h"
#include "b25/arib_std_b25.h"
#include "b25/b_cas_card.h"

namespace EARTH
{
namespace EX
{
class Buffer;
}
}

namespace ry0
{
namespace device
{
namespace PT3
{

static const int PAGE_SIZE          = 4096;
static const int BLOCK_COUNT        = 32;
static const int BLOCK_SIZE         = (PAGE_SIZE * 47 * 8);

    static const int EXCEPTION_NEW_DEVICE               = 0x00000001;
    static const int EXCEPTION_DELETE                   = 0x00000002;
    static const int EXCEPTION_OPEN                     = 0x00000004;
    static const int EXCEPTION_CLOSE                    = 0x00000008;
    static const int EXCEPTION_INIT_TUNER               = 0x00000010;
    static const int EXCEPTION_SET_TUNER_POWER_RESET    = 0x00000020;
    static const int EXCEPTION_SET_TUNER_SLEEP          = 0x00000040;
    static const int EXCEPTION_SET_STREAM_ENABLE        = 0x00000080;
    static const int EXCEPTION_SET_STREAM_GRAY          = 0x00000100;
    static const int EXCEPTION_OTHER                    = 0x80000000;

static const unsigned int NOT_SYNC_BYTE = 0x74;

class PT3Core;

class PT3Tuner : public Tuner
{
    friend class PT3Core;

private:
    CRITICAL_SECTION    _cs;
    PT3Core *           _core;
    Listener *          _listener;
    uint32_t            _tuner;
    char                _name[64];
    int                 _channel;
    bool                _recording;
    int                 _recfd;
    bool                _locked;

    // temporary
    SOCKET              _udp;
    struct sockaddr_in  _dst_addr;

    enum {
        ST_IDLE = 0,
        ST_READY,
        ST_RUN,
        ST_STOP}        _transfer;

    uint32_t            _blockIndex;
    EARTH::EX::Buffer * _buffer;

    ARIB_STD_B25 *  _b25;
    B_CAS_CARD *    _bcas;

    PT3Tuner(PT3Core *core, uint32_t tuner, HMODULE multi2_dll);
    ~PT3Tuner();

    void addPacket(uint32_t packet);

public:
    void setListener(Listener *listener);
    const char *name();
    Type type();
    LnbPower lnbPower();
    bool getCnAgc(uint32_t *cn100, uint32_t *agc, uint32_t *maxAgc);
    int channel();
    bool setChannel(int channel);
    bool startRecording(int fd);
    int stopRecording();
    bool isRecording();
    bool lock();
    void unlock();
    bool isLocked();

    // temporary
    bool startStreaming(struct sockaddr_in *);
    void stopStreaming();
    bool isStreaming();

    bool checkReady(uint32_t bloclIndex);
    void transfer();

    //
    static int scan(Tuner *tuners[], HMODULE multi2_dll);
};

} // PT3
} // device
} // ry0

#endif // __RY0_DEVICE_PT3_PT3TUNER_H__
