mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-09-01 18:01:13 +02:00
zapit/src/zapit.cpp: add support for adjusting volume per channel/pid
This commit is contained in:
@@ -21,11 +21,21 @@
|
|||||||
#define PAL 0
|
#define PAL 0
|
||||||
#define NTSC 1
|
#define NTSC 1
|
||||||
#define AUDIO_CONFIG_FILE "/var/tuxbox/config/zapit/audio.conf"
|
#define AUDIO_CONFIG_FILE "/var/tuxbox/config/zapit/audio.conf"
|
||||||
|
#define VOLUME_CONFIG_FILE "/var/tuxbox/config/zapit/volume.conf"
|
||||||
|
|
||||||
typedef std::map<t_channel_id, audio_map_set_t> audio_map_t;
|
typedef std::map<t_channel_id, audio_map_set_t> audio_map_t;
|
||||||
typedef audio_map_t::iterator audio_map_iterator_t;
|
typedef audio_map_t::iterator audio_map_iterator_t;
|
||||||
typedef std::map<transponder_id_t, time_t> sdt_tp_map_t;
|
typedef std::map<transponder_id_t, time_t> sdt_tp_map_t;
|
||||||
|
|
||||||
|
typedef std::pair<int, int> pid_pair_t;
|
||||||
|
typedef std::pair<t_channel_id, pid_pair_t> volume_pair_t;
|
||||||
|
typedef std::multimap<t_channel_id, pid_pair_t> volume_map_t;
|
||||||
|
typedef volume_map_t::iterator volume_map_iterator_t;
|
||||||
|
typedef std::pair<volume_map_iterator_t,volume_map_iterator_t> volume_map_range_t;
|
||||||
|
|
||||||
|
#define VOLUME_PERCENT_AC3 100
|
||||||
|
#define VOLUME_PERCENT_PCM 75
|
||||||
|
|
||||||
/* complete zapit start thread-parameters in a struct */
|
/* complete zapit start thread-parameters in a struct */
|
||||||
typedef struct ZAPIT_start_arg
|
typedef struct ZAPIT_start_arg
|
||||||
{
|
{
|
||||||
@@ -33,6 +43,7 @@ typedef struct ZAPIT_start_arg
|
|||||||
t_channel_id startchannelradio_id;
|
t_channel_id startchannelradio_id;
|
||||||
int uselastchannel;
|
int uselastchannel;
|
||||||
int video_mode;
|
int video_mode;
|
||||||
|
int volume;
|
||||||
int ci_clock;
|
int ci_clock;
|
||||||
} Z_start_arg;
|
} Z_start_arg;
|
||||||
|
|
||||||
@@ -89,6 +100,7 @@ class CZapit : public OpenThreads::Thread
|
|||||||
RECORD_MODE = 0x04
|
RECORD_MODE = 0x04
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OpenThreads::Mutex mutex;
|
||||||
bool started;
|
bool started;
|
||||||
bool event_mode;
|
bool event_mode;
|
||||||
bool firstzap;
|
bool firstzap;
|
||||||
@@ -99,10 +111,12 @@ class CZapit : public OpenThreads::Thread
|
|||||||
int def_audio_mode;
|
int def_audio_mode;
|
||||||
int aspectratio;
|
int aspectratio;
|
||||||
int mode43;
|
int mode43;
|
||||||
|
#if 0
|
||||||
unsigned int volume_left;
|
unsigned int volume_left;
|
||||||
unsigned int volume_right;
|
unsigned int volume_right;
|
||||||
unsigned int def_volume_left;
|
#endif
|
||||||
unsigned int def_volume_right;
|
int current_volume;
|
||||||
|
int volume_percent;
|
||||||
|
|
||||||
int currentMode;
|
int currentMode;
|
||||||
bool playbackStopForced;
|
bool playbackStopForced;
|
||||||
@@ -121,6 +135,7 @@ class CZapit : public OpenThreads::Thread
|
|||||||
CFrontend * live_fe;
|
CFrontend * live_fe;
|
||||||
|
|
||||||
audio_map_t audio_map;
|
audio_map_t audio_map;
|
||||||
|
volume_map_t vol_map;
|
||||||
//bool current_is_nvod;
|
//bool current_is_nvod;
|
||||||
//bool standby;
|
//bool standby;
|
||||||
t_channel_id lastChannelRadio;
|
t_channel_id lastChannelRadio;
|
||||||
@@ -130,6 +145,7 @@ class CZapit : public OpenThreads::Thread
|
|||||||
|
|
||||||
//void LoadAudioMap();
|
//void LoadAudioMap();
|
||||||
void SaveAudioMap();
|
void SaveAudioMap();
|
||||||
|
void SaveVolumeMap();
|
||||||
void SaveSettings(bool write_conf);
|
void SaveSettings(bool write_conf);
|
||||||
//void SaveChannelPids(CZapitChannel* channel);
|
//void SaveChannelPids(CZapitChannel* channel);
|
||||||
void RestoreChannelPids(CZapitChannel* channel);
|
void RestoreChannelPids(CZapitChannel* channel);
|
||||||
@@ -171,6 +187,7 @@ class CZapit : public OpenThreads::Thread
|
|||||||
Zapit_config config;
|
Zapit_config config;
|
||||||
CZapitSdtMonitor SdtMonitor;
|
CZapitSdtMonitor SdtMonitor;
|
||||||
void LoadAudioMap();
|
void LoadAudioMap();
|
||||||
|
void LoadVolumeMap();
|
||||||
void SaveChannelPids(CZapitChannel* channel);
|
void SaveChannelPids(CZapitChannel* channel);
|
||||||
virtual void ConfigFrontend();
|
virtual void ConfigFrontend();
|
||||||
bool StopPlayBack(bool send_pmt);
|
bool StopPlayBack(bool send_pmt);
|
||||||
@@ -224,5 +241,11 @@ class CZapit : public OpenThreads::Thread
|
|||||||
void SetCurrentChannelID(const t_channel_id channel_id) { live_channel_id = channel_id; };
|
void SetCurrentChannelID(const t_channel_id channel_id) { live_channel_id = channel_id; };
|
||||||
void SetLiveFrontend(CFrontend * fe) { if(fe) live_fe = fe; }
|
void SetLiveFrontend(CFrontend * fe) { if(fe) live_fe = fe; }
|
||||||
CFrontend * GetLiveFrontend() { return live_fe; };
|
CFrontend * GetLiveFrontend() { return live_fe; };
|
||||||
|
|
||||||
|
int GetPidVolume(t_channel_id channel_id, int pid, bool ac3 = false);
|
||||||
|
void SetPidVolume(t_channel_id channel_id, int pid, int percent);
|
||||||
|
void SetVolume(int vol);
|
||||||
|
int GetVolume() { return current_volume; };
|
||||||
|
int SetVolumePercent(int percent);
|
||||||
};
|
};
|
||||||
#endif /* __zapit_h__ */
|
#endif /* __zapit_h__ */
|
||||||
|
@@ -109,8 +109,7 @@ CZapit::CZapit()
|
|||||||
{
|
{
|
||||||
started = false;
|
started = false;
|
||||||
pmt_update_fd = -1;
|
pmt_update_fd = -1;
|
||||||
volume_left = 0, volume_right = 0;
|
//volume_left = 0, volume_right = 0;
|
||||||
def_volume_left = 0, def_volume_right = 0;
|
|
||||||
audio_mode = 0;
|
audio_mode = 0;
|
||||||
aspectratio=0;
|
aspectratio=0;
|
||||||
mode43=0;
|
mode43=0;
|
||||||
@@ -122,6 +121,8 @@ CZapit::CZapit()
|
|||||||
playing = false;
|
playing = false;
|
||||||
list_changed = false; // flag to indicate, allchans was changed
|
list_changed = false; // flag to indicate, allchans was changed
|
||||||
currentMode = 0;
|
currentMode = 0;
|
||||||
|
current_volume = 100;
|
||||||
|
volume_percent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CZapit::~CZapit()
|
CZapit::~CZapit()
|
||||||
@@ -240,6 +241,38 @@ void CZapit::SaveAudioMap()
|
|||||||
fclose(audio_config_file);
|
fclose(audio_config_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CZapit::LoadVolumeMap()
|
||||||
|
{
|
||||||
|
vol_map.clear();
|
||||||
|
FILE *volume_config_file = fopen(VOLUME_CONFIG_FILE, "r");
|
||||||
|
if (!volume_config_file) {
|
||||||
|
perror(VOLUME_CONFIG_FILE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t_channel_id chan;
|
||||||
|
int apid = 0;
|
||||||
|
int volume = 0;
|
||||||
|
char s[1000];
|
||||||
|
while (fgets(s, 1000, volume_config_file)) {
|
||||||
|
if (sscanf(s, "%llx %d %d", &chan, &apid, &volume) == 3)
|
||||||
|
vol_map.insert(volume_pair_t(chan, pid_pair_t(apid, volume)));
|
||||||
|
}
|
||||||
|
fclose(volume_config_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZapit::SaveVolumeMap()
|
||||||
|
{
|
||||||
|
FILE *volume_config_file = fopen(VOLUME_CONFIG_FILE, "w");
|
||||||
|
if (!volume_config_file) {
|
||||||
|
perror(VOLUME_CONFIG_FILE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (volume_map_iterator_t it = vol_map.begin(); it != vol_map.end(); ++it)
|
||||||
|
fprintf(volume_config_file, "%llx %d %d\n", (uint64_t) it->first, it->second.first, it->second.second);
|
||||||
|
|
||||||
|
fdatasync(fileno(volume_config_file));
|
||||||
|
fclose(volume_config_file);
|
||||||
|
}
|
||||||
|
|
||||||
void CZapit::LoadSettings()
|
void CZapit::LoadSettings()
|
||||||
{
|
{
|
||||||
@@ -285,6 +318,7 @@ void CZapit::LoadSettings()
|
|||||||
/**/
|
/**/
|
||||||
|
|
||||||
LoadAudioMap();
|
LoadAudioMap();
|
||||||
|
LoadVolumeMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CZapit::ConfigFrontend()
|
void CZapit::ConfigFrontend()
|
||||||
@@ -324,10 +358,10 @@ void CZapit::SaveChannelPids(CZapitChannel* channel)
|
|||||||
if(channel == NULL)
|
if(channel == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("[zapit] saving channel, apid %x sub pid %x mode %d volume %d\n", channel->getAudioPid(), dvbsub_getpid(), audio_mode, volume_right);
|
printf("[zapit] saving channel, apid %x sub pid %x mode %d volume %d\n", channel->getAudioPid(), dvbsub_getpid(), audio_mode, current_volume);
|
||||||
audio_map[channel->getChannelID()].apid = channel->getAudioPid();
|
audio_map[channel->getChannelID()].apid = channel->getAudioPid();
|
||||||
audio_map[channel->getChannelID()].mode = audio_mode;
|
audio_map[channel->getChannelID()].mode = audio_mode;
|
||||||
audio_map[channel->getChannelID()].volume = audioDecoder->getVolume();
|
audio_map[channel->getChannelID()].volume = current_volume;
|
||||||
audio_map[channel->getChannelID()].subpid = dvbsub_getpid();
|
audio_map[channel->getChannelID()].subpid = dvbsub_getpid();
|
||||||
tuxtx_subtitle_running(&audio_map[channel->getChannelID()].ttxpid, &audio_map[channel->getChannelID()].ttxpage, NULL);
|
tuxtx_subtitle_running(&audio_map[channel->getChannelID()].ttxpid, &audio_map[channel->getChannelID()].ttxpage, NULL);
|
||||||
}
|
}
|
||||||
@@ -344,19 +378,9 @@ void CZapit::RestoreChannelPids(CZapitChannel * channel)
|
|||||||
if (channel->getAudioChannel(i)->pid == pidmap->apid ) {
|
if (channel->getAudioChannel(i)->pid == pidmap->apid ) {
|
||||||
DBG("***** Setting audio!\n");
|
DBG("***** Setting audio!\n");
|
||||||
channel->setAudioChannel(i);
|
channel->setAudioChannel(i);
|
||||||
#if 0
|
|
||||||
if(we_playing && (channel->getAudioChannel(i)->audioChannelType != CZapitAudioChannel::MPEG))
|
|
||||||
ChangeAudioPid(i);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0 // to restore saved volume per channel if needed. after first zap its done by neutrino
|
|
||||||
if(firstzap) {
|
|
||||||
audioDecoder->setVolume(audio_map_it->second.volume, audio_map_it->second.volume);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
volume_left = volume_right = pidmap->volume;
|
|
||||||
audio_mode = pidmap->mode;
|
audio_mode = pidmap->mode;
|
||||||
|
|
||||||
dvbsub_setpid(pidmap->subpid);
|
dvbsub_setpid(pidmap->subpid);
|
||||||
@@ -374,12 +398,10 @@ void CZapit::RestoreChannelPids(CZapitChannel * channel)
|
|||||||
else
|
else
|
||||||
tuxtx_set_pid(pidmap->ttxpid, pidmap->ttxpage, (char *) tmplang.c_str());
|
tuxtx_set_pid(pidmap->ttxpid, pidmap->ttxpage, (char *) tmplang.c_str());
|
||||||
} else {
|
} else {
|
||||||
volume_left = volume_right = def_volume_left;
|
|
||||||
audio_mode = def_audio_mode;
|
audio_mode = def_audio_mode;
|
||||||
tuxtx_set_pid(0, 0, (char *) channel->getTeletextLang());
|
tuxtx_set_pid(0, 0, (char *) channel->getTeletextLang());
|
||||||
}
|
}
|
||||||
/* restore saved stereo / left / right channel mode */
|
/* restore saved stereo / left / right channel mode */
|
||||||
//audioDecoder->setVolume(volume_left, volume_right);
|
|
||||||
audioDecoder->setChannel(audio_mode);
|
audioDecoder->setChannel(audio_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,6 +574,85 @@ bool CZapit::ZapForRecord(const t_channel_id channel_id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set channel/pid volume percent, using current channel_id and pid, if those params is 0 */
|
||||||
|
void CZapit::SetPidVolume(t_channel_id channel_id, int pid, int percent)
|
||||||
|
{
|
||||||
|
if (!channel_id)
|
||||||
|
channel_id = live_channel_id;
|
||||||
|
|
||||||
|
if (!pid && (channel_id == live_channel_id) && current_channel)
|
||||||
|
pid = current_channel->getAudioPid();
|
||||||
|
|
||||||
|
INFO("############################### channel %llx pid %x map size %d percent %d", channel_id, pid, vol_map.size(), percent);
|
||||||
|
volume_map_range_t pids = vol_map.equal_range(channel_id);
|
||||||
|
for (volume_map_iterator_t it = pids.first; it != pids.second; ++it) {
|
||||||
|
if (it->second.first == pid) {
|
||||||
|
it->second.second = percent;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vol_map.insert(volume_pair_t(channel_id, pid_pair_t(pid, percent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return channel/pid volume percent, using current channel_id and pid, if those params is 0 */
|
||||||
|
int CZapit::GetPidVolume(t_channel_id channel_id, int pid, bool ac3)
|
||||||
|
{
|
||||||
|
int percent = -1;
|
||||||
|
|
||||||
|
if (!channel_id)
|
||||||
|
channel_id = live_channel_id;
|
||||||
|
|
||||||
|
if (!pid && (channel_id == live_channel_id) && current_channel)
|
||||||
|
pid = current_channel->getAudioPid();
|
||||||
|
|
||||||
|
volume_map_range_t pids = vol_map.equal_range(channel_id);
|
||||||
|
for (volume_map_iterator_t it = pids.first; it != pids.second; ++it) {
|
||||||
|
if (it->second.first == pid) {
|
||||||
|
percent = it->second.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (percent < 0) {
|
||||||
|
percent = ac3 ? VOLUME_PERCENT_AC3 : VOLUME_PERCENT_PCM;
|
||||||
|
if ((channel_id == live_channel_id) && current_channel) {
|
||||||
|
for (int i = 0; i < current_channel->getAudioChannelCount(); i++) {
|
||||||
|
if (pid == current_channel->getAudioPid(i)) {
|
||||||
|
percent = current_channel->getAudioChannel(i)->audioChannelType == CZapitAudioChannel::AC3 ?
|
||||||
|
VOLUME_PERCENT_AC3 : VOLUME_PERCENT_PCM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INFO("############################### channel %llx pid %x map size %d percent %d", channel_id, pid, vol_map.size(), percent);
|
||||||
|
return percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZapit::SetVolume(int vol)
|
||||||
|
{
|
||||||
|
current_volume = vol;
|
||||||
|
if (current_volume < 0)
|
||||||
|
current_volume = 0;
|
||||||
|
if (current_volume > 100)
|
||||||
|
current_volume = 100;
|
||||||
|
|
||||||
|
int value = (current_volume * volume_percent) / 100;
|
||||||
|
INFO("############ volume %d percent %d -> %d ############", current_volume, volume_percent, value);
|
||||||
|
audioDecoder->setVolume(value, value);
|
||||||
|
//volume_left = volume_right = current_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CZapit::SetVolumePercent(int percent)
|
||||||
|
{
|
||||||
|
int ret = volume_percent;
|
||||||
|
|
||||||
|
if (volume_percent != percent) {
|
||||||
|
volume_percent = percent;
|
||||||
|
SetVolume(current_volume);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void CZapit::SetAudioStreamType(CZapitAudioChannel::ZapitAudioChannelType audioChannelType)
|
void CZapit::SetAudioStreamType(CZapitAudioChannel::ZapitAudioChannelType audioChannelType)
|
||||||
{
|
{
|
||||||
const char *audioStr = "UNKNOWN";
|
const char *audioStr = "UNKNOWN";
|
||||||
@@ -581,6 +682,10 @@ void CZapit::SetAudioStreamType(CZapitAudioChannel::ZapitAudioChannelType audioC
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: bigger percent for AC3 only, what about AAC etc ? */
|
||||||
|
int newpercent = GetPidVolume(0, 0, audioChannelType == CZapitAudioChannel::AC3);
|
||||||
|
SetVolumePercent(newpercent);
|
||||||
|
|
||||||
printf("[zapit] starting %s audio\n", audioStr);
|
printf("[zapit] starting %s audio\n", audioStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1471,15 +1576,21 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd)
|
|||||||
case CZapitMessages::CMD_SET_VOLUME: {
|
case CZapitMessages::CMD_SET_VOLUME: {
|
||||||
CZapitMessages::commandVolume msgVolume;
|
CZapitMessages::commandVolume msgVolume;
|
||||||
CBasicServer::receive_data(connfd, &msgVolume, sizeof(msgVolume));
|
CBasicServer::receive_data(connfd, &msgVolume, sizeof(msgVolume));
|
||||||
|
#if 0
|
||||||
audioDecoder->setVolume(msgVolume.left, msgVolume.right);
|
audioDecoder->setVolume(msgVolume.left, msgVolume.right);
|
||||||
volume_left = msgVolume.left;
|
volume_left = msgVolume.left;
|
||||||
volume_right = msgVolume.right;
|
volume_right = msgVolume.right;
|
||||||
|
#endif
|
||||||
|
SetVolume(msgVolume.left);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CZapitMessages::CMD_GET_VOLUME: {
|
case CZapitMessages::CMD_GET_VOLUME: {
|
||||||
CZapitMessages::commandVolume msgVolume;
|
CZapitMessages::commandVolume msgVolume;
|
||||||
|
#if 0
|
||||||
msgVolume.left = volume_left;
|
msgVolume.left = volume_left;
|
||||||
msgVolume.right = volume_right;
|
msgVolume.right = volume_right;
|
||||||
|
#endif
|
||||||
|
msgVolume.left = msgVolume.right = current_volume;
|
||||||
CBasicServer::send_data(connfd, &msgVolume, sizeof(msgVolume));
|
CBasicServer::send_data(connfd, &msgVolume, sizeof(msgVolume));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1808,6 +1919,9 @@ bool CZapit::StopPlayBack(bool send_pmt)
|
|||||||
else
|
else
|
||||||
dvbsub_stop();
|
dvbsub_stop();
|
||||||
|
|
||||||
|
/* reset volume percent to 100% i.e. for media playback, should be safe
|
||||||
|
* because StartPlayBack will use defaults or saved value */
|
||||||
|
SetVolumePercent(100);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1821,6 +1935,7 @@ void CZapit::enterStandby(void)
|
|||||||
|
|
||||||
SaveSettings(true);
|
SaveSettings(true);
|
||||||
SaveAudioMap();
|
SaveAudioMap();
|
||||||
|
SaveVolumeMap();
|
||||||
StopPlayBack(true);
|
StopPlayBack(true);
|
||||||
|
|
||||||
if(!(currentMode & RECORD_MODE)) {
|
if(!(currentMode & RECORD_MODE)) {
|
||||||
@@ -1912,6 +2027,7 @@ bool CZapit::Start(Z_start_arg *ZapStart_arg)
|
|||||||
live_fe = CFEManager::getInstance()->getFE(0);
|
live_fe = CFEManager::getInstance()->getFE(0);
|
||||||
/* load configuration or set defaults if no configuration file exists */
|
/* load configuration or set defaults if no configuration file exists */
|
||||||
video_mode = ZapStart_arg->video_mode;
|
video_mode = ZapStart_arg->video_mode;
|
||||||
|
current_volume = ZapStart_arg->volume;
|
||||||
|
|
||||||
videoDemux = new cDemux();
|
videoDemux = new cDemux();
|
||||||
videoDemux->Open(DMX_VIDEO_CHANNEL);
|
videoDemux->Open(DMX_VIDEO_CHANNEL);
|
||||||
@@ -2088,6 +2204,7 @@ void CZapit::run()
|
|||||||
SaveChannelPids(current_channel);
|
SaveChannelPids(current_channel);
|
||||||
SaveSettings(true);
|
SaveSettings(true);
|
||||||
SaveAudioMap();
|
SaveAudioMap();
|
||||||
|
SaveVolumeMap();
|
||||||
StopPlayBack(true);
|
StopPlayBack(true);
|
||||||
CFEManager::getInstance()->saveSettings(true);
|
CFEManager::getInstance()->saveSettings(true);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user