/*
 * cdda_lib.h: The disc drive access functions
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id: cdda_device.h,v 1.1.1.2 2005/06/27 13:34:02 cm Exp $
 */

#ifndef __CDDADEVICE_H
#define __CDDADEVICE_H

#include <sys/types.h>
#include <cdio/cdtext.h>
#include <cdio/cdio.h>
#include <vdr/thread.h>
#include "cdda_lib.h"

#define CDDA_CANNOT_EJECT_MEDIA    -3
#define CDDA_OUT_OF_MEMORY         -2
#define CDDA_CANNOT_OPEN_DEVICE	   -1
#define CDDA_FAIL                   0
#define CDDA_SUCCESS                1

#define CDDA_INVALID_SEEK          -1
#define CDDA_SEEK_SET               1
#define CDDA_SEEK_END               2
#define CDDA_SEEK_CUR               3

#define CDDA_EOF                   -1

#define CDDA_SECTORS_MAX            24

#define CDDA_AUDIO_FRAMESIZE        2016

//                                  1764 * 4
#define POSITIONTOFRAMES(s)         ((s) / 7056)
//                                  44100 * 4
#define POSITIONTOSECONDS(s)        ((s) / 176400)

// suppress the need to include cdda_cddb.h
class cCddaCddb;

class cCddaCdtext {
  private:
    char *p_title;
    char *p_performer;
    char *p_genre;
    char *p_message;
    char *p_arranger;
    char *p_composer;
    char *p_songwriter;
    char *p_discid;
    char *p_isrc;
    char *p_tocinfo;
    char *p_tocinfo2;
  public:
    cCddaCdtext();
    ~cCddaCdtext();
    const char *GetTitle(void) { return p_title; };
    const char *SetTitle(const char *title);
    const char *GetPerformer(void) { return p_performer; };
    const char *SetPerformer(const char *performer);
    const char *GetGenre(void) { return p_genre; };
    const char *SetGenre(const char *genre);
    const char *GetMessage(void) { return p_message; };
    const char *SetMessage(const char *message);
    const char *GetArranger(void) { return p_arranger; };
    const char *SetArranger(const char *arranger);
    const char *GetComposer(void) { return p_composer; };
    const char *SetComposer(const char *composer);
    const char *GetSongwriter(void) { return p_songwriter; };
    const char *SetSongwriter(const char *songwriter);
    const char *GetDiscId(void) { return p_discid; };
    const char *SetDiscId(const char *discid);
    const char *GetIsrc(void) { return p_isrc; };
    const char *SetIsrc(const char *isrc);
    const char *GetTocInfo(void) { return p_tocinfo; };
    const char *SetTocInfo(const char *tocinfo);
    const char *GetTocInfo2(void) { return p_tocinfo2; };
    const char *SetTocInfo2(const char *tocinfo2);
};

class cCddaTrack {
  private:
    char numChannels;
    unsigned char buffer[CDIO_CD_FRAMESIZE_RAW * CDDA_SECTORS_MAX];
    long frameBuffLen;
    unsigned long readPosition;
    track_t trackNum;
    CdIo_t *p_cdIo; 
    lsn_t startLsn, endLsn, currentLsn;
    track_format_t trackFormat;
    cCddaCdtext *po_cdtext;
    void ReadCdtext(void);
    void Initialize(void);
  public:
    cCddaTrack(CdIo_t *cdIo, track_t index);
    ~cCddaTrack();
    bool isAudio(void);
    unsigned long GetOffset(void);
    unsigned long GetLength(void);
    unsigned long GetPosition(void) { return readPosition; };
    // return the number of bytes from the start
    int GetChannels(void);
    unsigned char *Read(int &length, long &position);
    long Seek(long offset, int whence);
    cCddaCdtext *Cdtext(void) { return po_cdtext; };
    void SetCdtext(cCddaCdtext *obj);
};

class cCddaTracks {
  private:
    cCddaTrack *po_track[CDIO_CD_MAX_TRACKS];
    CdIo_t *p_cdIo;
    track_t firstTrack;
    track_t numTracks;
  public:
    cCddaTracks(CdIo_t *cdIo);
    ~cCddaTracks();
    unsigned int GetFirstNum(void);
    unsigned int GetNumTracks(void);
    cCddaTrack *Item(track_t index);
    unsigned long GetLength(void);
};

class cCddaDisc {
  private:
    bool cdtextDirty;
    unsigned long cddbId;
    cCddaTracks *po_tracks;
    cCddaCddb *po_cddb;
    CdIo_t *p_cdIo;
    discmode_t discMode;
    cCddaCdtext *po_cdtext;
    void ReadCdtext(void);
    unsigned int GetSum(unsigned int num);
    unsigned long GetCddbId(void);
  public:
    cCddaDisc(CdIo_t *cdIo);
    ~cCddaDisc();
    bool isAudio(void);
    bool isCdtextDirty(void) { return cdtextDirty; };
    bool SetCdtextDirty(bool dirty);
    cCddaTracks *Tracks(void);
    void ReadCddb(const char *fqdn, unsigned int port, const char *cacheDir);
    cCddaCdtext *Cdtext(void) { return po_cdtext; };
    void SetCdtext(cCddaCdtext *obj);
};

class cCddaDevice : public cReferenceCounter {
  private:
    char *p_device;
    CdIo_t *p_cdIo;
    cCddaDisc *po_disc;
  public:
    cCddaDevice();
    ~cCddaDevice();
    int Open(const char *name);
    int Close(void);
    cCddaDisc *Disc();
    int Eject(void);
    bool isOpen(void) { return (NULL != p_cdIo); };
};

#endif
