diff --git a/libtriple/audio_td.cpp b/libtriple/audio_td.cpp new file mode 100644 index 0000000..8350118 --- /dev/null +++ b/libtriple/audio_td.cpp @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include + + +#include +#define AUDIO_DEVICE "/dev/" DEVICE_NAME_AUDIO +#include "audio_td.h" + +cAudio * audioDecoder = NULL; + +cAudio::cAudio(void *, void *, void *) +{ + fd = -1; + openDevice(); + Muted = false; +} + +cAudio::~cAudio(void) +{ + closeDevice(); +} + +void cAudio::openDevice(void) +{ + if (fd < 0) + { + if ((fd = open(AUDIO_DEVICE, O_RDWR)) < 0) + fprintf(stderr, "cAudio::openDevice: open failed (%m)\n"); + } + else + fprintf(stderr, "cAudio::openDevice: already open (fd = %d)\n", fd); +} + +void cAudio::closeDevice(void) +{ + if (fd >= 0) + close(fd); + fd = -1; +} + +int cAudio::do_mute(bool enable, bool remember) +{ + lt_debug("cAudio::%s(%d, %d)\n", __FUNCTION__, enable, remember); + int ret; + if (remember) + Muted = enable; + ret = ioctl(fd, MPEG_AUD_SET_MUTE, enable); + if (ret < 0) + fprintf(stderr, "cAudio::%s(%d) failed (%m)\n", __FUNCTION__, (int)enable); + return ret; +} + +int map_volume(const int volume) +{ + unsigned char vol = volume; + if (vol > 100) + vol = 100; + +// vol = (invlog63[volume] + 1) / 2; + vol = 31 - vol * 31 / 100; + return vol; +} + +int cAudio::setVolume(unsigned int left, unsigned int right) +{ +// int avsfd; + int ret; + int vl = map_volume(left); + int vr = map_volume(right); + int v = map_volume((left + right) / 2); +// if (settings.volume_type == CControld::TYPE_OST || forcetype == (int)CControld::TYPE_OST) + { + AUDVOL vol; + vol.frontleft = vl; + vol.frontright = vr; + vol.rearleft = vl; + vol.rearright = vr; + vol.center = v; + vol.lfe = v; + ret = ioctl(fd, MPEG_AUD_SET_VOL, &vol); + if (ret < 0) + fprintf(stderr, "cAudio::setVolume MPEG_AUD_SET_VOL failed (%m)\n"); + return ret; + } +#if 0 + else if (settings.volume_type == CControld::TYPE_AVS || forcetype == (int)CControld::TYPE_AVS) + { + if ((avsfd = open(AVS_DEVICE, O_RDWR)) < 0) + perror("[controld] " AVS_DEVICE); + else { + if (ioctl(avsfd, IOC_AVS_SET_VOLUME, v)) + perror("[controld] IOC_AVS_SET_VOLUME"); + close(avsfd); + return 0; + } + } + fprintf(stderr, "CAudio::setVolume: invalid settings.volume_type = %d\n", settings.volume_type); + return -1; +#endif +} + +int cAudio::Start(void) +{ + int ret; + ret = ioctl(fd, MPEG_AUD_PLAY); + /* this seems to be not strictly necessary since neutrino + re-mutes all the time, but is certainly more correct */ + ioctl(fd, MPEG_AUD_SET_MUTE, Muted); + return ret; +} + +int cAudio::Stop(void) +{ + return ioctl(fd, MPEG_AUD_STOP); +} + +bool cAudio::Pause(bool /*Pcm*/) +{ + return true; +}; + +void cAudio::SetSyncMode(AVSYNC_TYPE /*Mode*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::SetStreamType(AUDIO_FORMAT type) +{ + int bypass_disable; + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + StreamType = type; + + if (StreamType != AUDIO_FMT_DOLBY_DIGITAL && StreamType != AUDIO_FMT_MPEG && StreamType != AUDIO_FMT_MPG1) + fprintf(stderr, "cAudio::%s unhandled AUDIO_FORMAT %d\n", __FUNCTION__, StreamType); + + bypass_disable = (StreamType != AUDIO_FMT_DOLBY_DIGITAL); + setBypassMode(bypass_disable); + + if (StreamType == AUDIO_FMT_MPEG) + ioctl(fd, MPEG_AUD_SET_STREAM_TYPE, AUD_STREAM_TYPE_PES); + if (StreamType == AUDIO_FMT_MPG1) + ioctl(fd, MPEG_AUD_SET_STREAM_TYPE, AUD_STREAM_TYPE_MPEG1); +}; + +int cAudio::setChannel(int /*channel*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +int cAudio::PrepareClipPlay(int /*uNoOfChannels*/, int /*uSampleRate*/, int /*uBitsPerSample*/, int /*bLittleEndian*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +int cAudio::WriteClip(unsigned char * /*buffer*/, int /*size*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +int cAudio::StopClip() +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + unsigned int atype; + static const int freq_mpg[] = {44100, 48000, 32000, 0}; + static const int freq_ac3[] = {48000, 44100, 32000, 0}; + scratchl2 i; + if (ioctl(fd, MPEG_AUD_GET_DECTYP, &atype) < 0) + perror("cAudio::getAudioInfo MPEG_AUD_GET_DECTYP"); + if (ioctl(fd, MPEG_AUD_GET_STATUS, &i) < 0) + perror("cAudio::getAudioInfo MPEG_AUD_GET_STATUS"); + + type = atype; +#if 0 +/* this does not work, some of the values are negative?? */ + AMPEGStatus A; + memcpy(&A, &i.word00, sizeof(i.word00)); + layer = A.audio_mpeg_layer; + mode = A.audio_mpeg_mode; + bitrate = A.audio_mpeg_bitrate; + switch(A.audio_mpeg_frequency) +#endif + /* layer and bitrate are not used anyway... */ + layer = 0; //(i.word00 >> 17) & 3; + bitrate = 0; //(i.word00 >> 12) & 3; + switch (type) + { + case 0: /* MPEG */ + mode = (i.word00 >> 6) & 3; + freq = freq_mpg[(i.word00 >> 10) & 3]; + break; + case 1: /* AC3 */ + mode = (i.word00 >> 28) & 7; + freq = freq_ac3[(i.word00 >> 16) & 3]; + break; + default: + mode = 0; + freq = 0; + } + //fprintf(stderr, "type: %d layer: %d freq: %d bitrate: %d mode: %d\n", type, layer, freq, bitrate, mode); +}; + +void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::SetSpdifDD(bool /*enable*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::ScheduleMute(bool /*On*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::EnableAnalogOut(bool /*enable*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::setBypassMode(bool disable) +{ + /* disable = true: audio is MPEG, disable = false: audio is AC3 */ + if (disable) + { + ioctl(fd, MPEG_AUD_SET_MODE, AUD_MODE_MPEG); + return; + } + /* dvb2001 does always set AUD_MODE_DTS before setting AUD_MODE_AC3, + this might be some workaround, so we do the same... */ + ioctl(fd, MPEG_AUD_SET_MODE, AUD_MODE_DTS); + ioctl(fd, MPEG_AUD_SET_MODE, AUD_MODE_AC3); + return; + /* all those ioctl aways return "invalid argument", but they seem to + work anyway, so there's no use in checking the return value */ +} diff --git a/libtriple/audio_td.h b/libtriple/audio_td.h new file mode 100644 index 0000000..7178ecf --- /dev/null +++ b/libtriple/audio_td.h @@ -0,0 +1,88 @@ +/* public header file */ + +#ifndef _AUDIO_TD_H_ +#define _AUDIO_TD_H_ + +#include + +typedef enum +{ + AUDIO_SYNC_WITH_PTS, + AUDIO_NO_SYNC, + AUDIO_SYNC_AUDIO_MASTER +} AUDIO_SYNC_MODE; + +typedef enum +{ + AUDIO_FMT_AUTO = 0, + AUDIO_FMT_MPEG, + AUDIO_FMT_MP3, + AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_AAC, + AUDIO_FMT_AAC_PLUS, + AUDIO_FMT_DD_PLUS, + AUDIO_FMT_DTS, + AUDIO_FMT_AVS, + AUDIO_FMT_MLP, + AUDIO_FMT_WMA, + AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback + AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP +} AUDIO_FORMAT; + +class cAudio +{ + private: + int fd; + bool Muted; + + AUDIO_FORMAT StreamType; + AUDIO_SYNC_MODE SyncMode; + bool started; + + int volume; + + void openDevice(void); + void closeDevice(void); + + int do_mute(bool enable, bool remember); + void setBypassMode(bool disable); + public: + /* construct & destruct */ + cAudio(void *, void *, void *); + ~cAudio(void); + + void *GetHandle() { return NULL; }; + /* shut up */ + int mute(bool remember = true) { return do_mute(true, remember); }; + int unmute(bool remember = true) { return do_mute(false, remember); }; + + /* volume, min = 0, max = 255 */ + int setVolume(unsigned int left, unsigned int right); + int getVolume(void) { return volume;} + bool getMuteStatus(void) { return Muted; }; + + /* start and stop audio */ + int Start(void); + int Stop(void); + bool Pause(bool Pcm = true); + void SetStreamType(AUDIO_FORMAT type); +#define AVSYNC_TYPE int + void SetSyncMode(AVSYNC_TYPE Mode); + + /* select channels */ + int setChannel(int channel); + int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian); + int WriteClip(unsigned char * buffer, int size); + int StopClip(); + void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode); + void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level); + bool IsHdmiDDSupported() { return false; }; + void SetHdmiDD(bool) { return; }; + void SetSpdifDD(bool enable); + void ScheduleMute(bool On); + void EnableAnalogOut(bool enable); +}; + +#endif +