diff --git a/src/zapit/include/zapit/zapit.h b/src/zapit/include/zapit/zapit.h index 880ddcae0..2c77eb030 100644 --- a/src/zapit/include/zapit/zapit.h +++ b/src/zapit/include/zapit/zapit.h @@ -21,11 +21,21 @@ #define PAL 0 #define NTSC 1 #define AUDIO_CONFIG_FILE "/var/tuxbox/config/zapit/audio.conf" +#define VOLUME_CONFIG_FILE "/var/tuxbox/config/zapit/volume.conf" typedef std::map audio_map_t; typedef audio_map_t::iterator audio_map_iterator_t; typedef std::map sdt_tp_map_t; +typedef std::pair pid_pair_t; +typedef std::pair volume_pair_t; +typedef std::multimap volume_map_t; +typedef volume_map_t::iterator volume_map_iterator_t; +typedef std::pair volume_map_range_t; + +#define VOLUME_PERCENT_AC3 100 +#define VOLUME_PERCENT_PCM 75 + /* complete zapit start thread-parameters in a struct */ typedef struct ZAPIT_start_arg { @@ -33,6 +43,7 @@ typedef struct ZAPIT_start_arg t_channel_id startchannelradio_id; int uselastchannel; int video_mode; + int volume; int ci_clock; } Z_start_arg; @@ -89,6 +100,7 @@ class CZapit : public OpenThreads::Thread RECORD_MODE = 0x04 }; + OpenThreads::Mutex mutex; bool started; bool event_mode; bool firstzap; @@ -99,10 +111,12 @@ class CZapit : public OpenThreads::Thread int def_audio_mode; int aspectratio; int mode43; +#if 0 unsigned int volume_left; unsigned int volume_right; - unsigned int def_volume_left; - unsigned int def_volume_right; +#endif + int current_volume; + int volume_percent; int currentMode; bool playbackStopForced; @@ -121,6 +135,7 @@ class CZapit : public OpenThreads::Thread CFrontend * live_fe; audio_map_t audio_map; + volume_map_t vol_map; //bool current_is_nvod; //bool standby; t_channel_id lastChannelRadio; @@ -130,6 +145,7 @@ class CZapit : public OpenThreads::Thread //void LoadAudioMap(); void SaveAudioMap(); + void SaveVolumeMap(); void SaveSettings(bool write_conf); //void SaveChannelPids(CZapitChannel* channel); void RestoreChannelPids(CZapitChannel* channel); @@ -171,6 +187,7 @@ class CZapit : public OpenThreads::Thread Zapit_config config; CZapitSdtMonitor SdtMonitor; void LoadAudioMap(); + void LoadVolumeMap(); void SaveChannelPids(CZapitChannel* channel); virtual void ConfigFrontend(); 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 SetLiveFrontend(CFrontend * fe) { if(fe) live_fe = 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__ */ diff --git a/src/zapit/src/zapit.cpp b/src/zapit/src/zapit.cpp index a7ae43bfd..143ee9ef3 100644 --- a/src/zapit/src/zapit.cpp +++ b/src/zapit/src/zapit.cpp @@ -109,8 +109,7 @@ CZapit::CZapit() { started = false; pmt_update_fd = -1; - volume_left = 0, volume_right = 0; - def_volume_left = 0, def_volume_right = 0; + //volume_left = 0, volume_right = 0; audio_mode = 0; aspectratio=0; mode43=0; @@ -122,6 +121,8 @@ CZapit::CZapit() playing = false; list_changed = false; // flag to indicate, allchans was changed currentMode = 0; + current_volume = 100; + volume_percent = 0; } CZapit::~CZapit() @@ -240,6 +241,38 @@ void CZapit::SaveAudioMap() 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() { @@ -285,6 +318,7 @@ void CZapit::LoadSettings() /**/ LoadAudioMap(); + LoadVolumeMap(); } void CZapit::ConfigFrontend() @@ -324,10 +358,10 @@ void CZapit::SaveChannelPids(CZapitChannel* channel) if(channel == NULL) 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()].mode = audio_mode; - audio_map[channel->getChannelID()].volume = audioDecoder->getVolume(); + audio_map[channel->getChannelID()].volume = current_volume; audio_map[channel->getChannelID()].subpid = dvbsub_getpid(); 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 ) { DBG("***** Setting audio!\n"); 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; dvbsub_setpid(pidmap->subpid); @@ -374,12 +398,10 @@ void CZapit::RestoreChannelPids(CZapitChannel * channel) else tuxtx_set_pid(pidmap->ttxpid, pidmap->ttxpage, (char *) tmplang.c_str()); } else { - volume_left = volume_right = def_volume_left; audio_mode = def_audio_mode; tuxtx_set_pid(0, 0, (char *) channel->getTeletextLang()); } /* restore saved stereo / left / right channel mode */ - //audioDecoder->setVolume(volume_left, volume_right); audioDecoder->setChannel(audio_mode); } @@ -552,6 +574,85 @@ bool CZapit::ZapForRecord(const t_channel_id channel_id) 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) { const char *audioStr = "UNKNOWN"; @@ -581,6 +682,10 @@ void CZapit::SetAudioStreamType(CZapitAudioChannel::ZapitAudioChannelType audioC 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); } @@ -1471,15 +1576,21 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_SET_VOLUME: { CZapitMessages::commandVolume msgVolume; CBasicServer::receive_data(connfd, &msgVolume, sizeof(msgVolume)); +#if 0 audioDecoder->setVolume(msgVolume.left, msgVolume.right); volume_left = msgVolume.left; volume_right = msgVolume.right; +#endif + SetVolume(msgVolume.left); break; } case CZapitMessages::CMD_GET_VOLUME: { CZapitMessages::commandVolume msgVolume; +#if 0 msgVolume.left = volume_left; msgVolume.right = volume_right; +#endif + msgVolume.left = msgVolume.right = current_volume; CBasicServer::send_data(connfd, &msgVolume, sizeof(msgVolume)); break; } @@ -1808,6 +1919,9 @@ bool CZapit::StopPlayBack(bool send_pmt) else 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; } @@ -1821,6 +1935,7 @@ void CZapit::enterStandby(void) SaveSettings(true); SaveAudioMap(); + SaveVolumeMap(); StopPlayBack(true); if(!(currentMode & RECORD_MODE)) { @@ -1912,6 +2027,7 @@ bool CZapit::Start(Z_start_arg *ZapStart_arg) live_fe = CFEManager::getInstance()->getFE(0); /* load configuration or set defaults if no configuration file exists */ video_mode = ZapStart_arg->video_mode; + current_volume = ZapStart_arg->volume; videoDemux = new cDemux(); videoDemux->Open(DMX_VIDEO_CHANNEL); @@ -2088,6 +2204,7 @@ void CZapit::run() SaveChannelPids(current_channel); SaveSettings(true); SaveAudioMap(); + SaveVolumeMap(); StopPlayBack(true); CFEManager::getInstance()->saveSettings(true);