diff --git a/HISTORY b/HISTORY index 63e4bf6..6b108d8 100644 --- a/HISTORY +++ b/HISTORY @@ -54,6 +54,10 @@ VDR Plugin 'femon' Revision History - Backported changes and fixes from version 0.1.2. +2004-06-11: Version 0.0.6 + +- Backported the "AC3 Stream Information" feature from version 0.1.3. + ------------------------- 2004-05-18: Version 0.1.0 @@ -73,3 +77,7 @@ VDR Plugin 'femon' Revision History - Fixed the channel switch bug (reported by Stefan Lucke). - Nid/Tid/Rid are now included in translations. - Added video format and aspect ratio symbols into status window. + +2004-06-11: Version 0.1.3 + +- Added "AC-3 Stream Information" display mode (Thanks to Lothar Englisch). diff --git a/README b/README index ae6611e..52369cc 100644 --- a/README +++ b/README @@ -10,9 +10,7 @@ See the file COPYING for license information. Requirements: -Ph.D. in Astro Physics and preferably a six-pack waiting in a fridge. -Never trust a Klingon. "Qu'vaD lI' De'vam". Beam me up, Scotty! -You're number six! I'm number two. YARRR! +VDR & DVB. BMW & Ph.D.. BEER. YARRR! Description: @@ -30,7 +28,41 @@ bitrate calculation algorithm originates from the 'dvbstream' application by Dave Chapman and the stream information routines from the 'libdvb' library by Metzler Brothers. -Shortcomings / Todo list / Important Notes: +Terminology: + +-------------------------------------------------------------- +|## Channel Name ############################# DD 16:9 PAL ##| +|[=====Signal Strength in % =============|=================]| +|[=====Signal-to-Noise Ratio in % ========|=================]| +| STR: #0000 (0%) BER: #00000000 Video: 0 Mbit/s | +| SNR: #0000 (0%) UNC: #00000000 Audio: 0 kbit/s | +| [LOCK] [SIGNAL] [CARRIER] [VITERBI] [SYNC] | +-------------------------------------------------------------- + +STR - Signal strength +SNR - Signal-to-noise ratio +BER - Bit error rate +UNC - Uncorrected blocks +Video - Calculated video bitrate in Mbit/s +Audio - Calculated audio / AC-3 bitrate in kbit/s (only first PID) + +LOCK - Everything's working... +SIGNAL - Found something above the noise level +CARRIER - Found a DVB signal +VITERBI - FEC (forward error correction) is stable +SYNC - Found sync bytes + +Installation: + +cd /put/your/path/here/VDR/PLUGINS/src +tar -xzf /put/your/path/here/vdr-femon-X.Y.Z.tar.gz +ln -s femon-X.Y.Z femon +cd /put/your/path/here/VDR +make +make plugins +./vdr -Pfemon + +Notes: - The plugin supports only those DVB cards with _one_ frontend (do any cards with multiple frontends even exist?), because I haven't yet figured howto do diff --git a/femon.c b/femon.c index ec38154..4ff6028 100644 --- a/femon.c +++ b/femon.c @@ -85,9 +85,10 @@ bool cPluginFemon::SetupParse(const char *Name, const char *Value) cMenuFemonSetup::cMenuFemonSetup(void) { - dispmodes[0] = tr("basic"); - dispmodes[1] = tr("transponder"); - dispmodes[2] = tr("stream"); + dispmodes[modeBasic] = tr("basic"); + dispmodes[modeTransponder] = tr("transponder"); + dispmodes[modeStream] = tr("stream"); + dispmodes[modeAC3] = tr("AC-3"); Setup(); } diff --git a/femon.h b/femon.h index 495166f..92b1d19 100644 --- a/femon.h +++ b/femon.h @@ -11,7 +11,7 @@ #include -static const char *VERSION = "0.0.5"; +static const char *VERSION = "0.0.6"; static const char *DESCRIPTION = "DVB Signal Information Monitor (OSD)"; static const char *MAINMENUENTRY = "Signal Information"; diff --git a/femoncfg.h b/femoncfg.h index b8a9407..cf5f5b3 100644 --- a/femoncfg.h +++ b/femoncfg.h @@ -13,6 +13,7 @@ enum dispModes { modeBasic, modeTransponder, modeStream, + modeAC3, modeMaxNumber }; diff --git a/femoni18n.c b/femoni18n.c index 73b86cc..7c96464 100644 --- a/femoni18n.c +++ b/femoni18n.c @@ -758,7 +758,7 @@ const tI18nPhrase Phrases[] = { "Hz", // Français "Hz", // Norsk "Hz", // suomi - "Hz", // Polski + "Hz", // Polski "Hz", // Español "Hz", // ÅëëçíéêÜ (Greek) "Hz", // Svenska @@ -766,7 +766,7 @@ const tI18nPhrase Phrases[] = { "Hz", // Magyar "Hz", // Català #if VDRVERSNUM >= 10302 - "Hz", // ÀãááÚØÙ (Russian) + "³æ", // ÀãááÚØÙ (Russian) #endif }, { "Aspect Ratio", // English @@ -986,27 +986,7 @@ const tI18nPhrase Phrases[] = { "kHz", // Magyar "kHz", // Català #if VDRVERSNUM >= 10302 - "kHz", // ÀãááÚØÙ (Russian) -#endif - }, - { "MPEG Layer", // English - "MPEG Layer", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "MPEG-kerros", // suomi - "", // Polski - "", // Español - "", // ÅëëçíéêÜ (Greek) - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Català -#if VDRVERSNUM >= 10302 - "", // ÀãááÚØÙ (Russian) + "Ú³æ", // ÀãááÚØÙ (Russian) #endif }, { "Nid", // English @@ -1067,6 +1047,586 @@ const tI18nPhrase Phrases[] = { "Rid", // Català #if VDRVERSNUM >= 10302 "Rid", // ÀãááÚØÙ (Russian) +#endif + }, + { "dB", // English + "dB", // Deutsch + "dB", // Slovenski + "dB", // Italiano + "dB", // Nederlands + "dB", // Português + "dB", // Français + "dB", // Norsk + "dB", // suomi + "dB", // Polski + "dB", // Español + "dB", // ÅëëçíéêÜ (Greek) + "dB", // Svenska + "dB", // Romaneste + "dB", // Magyar + "dB", // Català +#if VDRVERSNUM >= 10302 + "dB", // ÀãááÚØÙ (Russian) +#endif + }, + { "not indicated", // English + "nicht angezeigt", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "ei ilmaistu", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "AC-3", // English + "AC-3", // Deutsch + "AC-3", // Slovenski + "AC-3", // Italiano + "AC-3", // Nederlands + "AC-3", // Português + "AC-3", // Français + "AC-3", // Norsk + "AC-3", // suomi + "AC-3", // Polski + "AC-3", // Español + "AC-3", // ÅëëçíéêÜ (Greek) + "AC-3", // Svenska + "AC-3", // Romaneste + "AC-3", // Magyar + "AC-3", // Català +#if VDRVERSNUM >= 10302 + "AC-3", // ÀãááÚØÙ (Russian) +#endif + }, + { "AC-3 Stream", // English + "AC-3 Stream", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "AC-3 ääniraita", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Frame Size", // English + "Frame Größe", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Kehyksen koko", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Bit Stream Mode", // English + "Bitstream Modus", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Lähetteen tyyppi", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Audio Coding Mode", // English + "Audio Coding Modus", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Äänikoodaus", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Center Mix Level", // English + "Center Mix Pegel", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Keskikanavan taso", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Surround Mix Level", // English + "Surround Mix Pegel", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Tehostekanavien taso", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Dolby Surround Mode", // English + "Dolby Surround Modus", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Dolby Surround -moodi", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Low Frequency Effects", // English + "Tieftöner Effekt", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "LFE-kanava", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Dialogue Normalization", // English + "Dialog Normalisation", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Dialogin normalisointi", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Complete Main (CM)", // English + "Complete Main (CM)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Pääasiallinen (CM)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Music and Effects (ME)", // English + "Musik und Effekte (ME)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Musiikki ja tehosteet (ME)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Visually Impaired (VI)", // English + "Sehbehindert (VI)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Näkörajoitteinen (VI)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Hearing Impaired (HI)", // English + "Hörbehindert (HI)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Kuulorajoitteinen (HI)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Dialogue (D)", // English + "Dialog (D)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Vuoropuhelu (D)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Commentary (C)", // English + "Kommentar (C)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Kommentointi (C)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Emergency (E)", // English + "Notfall (E)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Hätätiedote (E)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Voice Over (VO)", // English + "überlagerte Stimme (VO)", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Päälle puhuttu (VO)", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Karaoke", // English + "Karaoke", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Karaoke", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Ch1", // English "Channel 1" + "Kanal1", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "kan. 1", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "Ch2", // English "Channel 2" + "Kanal2", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "kan. 2", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "C", // English "Center" + "C", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "K", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "L", // English "Left" + "L", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "V", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "R", // English "Right" + "R", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "O", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "S", // English "Surround" + "S", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "T", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "SL", // English "Surround Left" + "SL", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "TV", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) +#endif + }, + { "SR", // English "Surround Right" + "SR", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "TO", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10302 + "", // ÀãááÚØÙ (Russian) #endif }, { NULL } diff --git a/femonosd.c b/femonosd.c index f9619ad..0029c23 100644 --- a/femonosd.c +++ b/femonosd.c @@ -32,6 +32,7 @@ #define OSDSTATUSWIN_X(col) ((col == 7) ? 475 : (col == 6) ? 410 : (col == 5) ? 275 : (col == 4) ? 220 : (col == 3) ? 125 : (col==2) ? 70 : 15) #define OSDSTATUSWIN_XC(col,txt) (((col - 1) * SCREENWIDTH / 6) + ((SCREENWIDTH / 6 - cOsd::WidthInCells(txt) * cOsd::CellWidth()) / 2)) #define BARWIDTH(x) (OSDWIDTH * x / 100) +#define DELTA 2 cFemonOsd::cFemonOsd(void) #if VDRVERSNUM >= 10300 @@ -103,7 +104,7 @@ void cFemonOsd::DrawStatusWindow(void) m_Osd->Fill(BARWIDTH(femonConfig.greenlimit), OSDSTATUSWIN_Y(offset+3), signal, OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrGreen, m_StatusWindow); } } - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; if (snr > 0) { snr = BARWIDTH(snr); m_Osd->Fill(0, OSDSTATUSWIN_Y(offset+3), min(BARWIDTH(femonConfig.redlimit), snr), OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrRed, m_StatusWindow); @@ -114,7 +115,7 @@ void cFemonOsd::DrawStatusWindow(void) m_Osd->Fill(BARWIDTH(femonConfig.greenlimit), OSDSTATUSWIN_Y(offset+3), snr, OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrGreen, m_StatusWindow); } } - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), "STR:", clrWhite, clrBackground, m_StatusWindow); snprintf(buf, sizeof(buf), "%04x", m_Signal); m_Osd->Text(OSDSTATUSWIN_X(2), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow); @@ -128,7 +129,7 @@ void cFemonOsd::DrawStatusWindow(void) if (m_Receiver) snprintf(buf, sizeof(buf), "%.2f %s", m_Receiver->VideoBitrate(), tr("Mbit/s")); else snprintf(buf, sizeof(buf), "--- %s", tr("Mbit/s")); m_Osd->Text(OSDSTATUSWIN_X(7), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), "SNR:", clrWhite, clrBackground, m_StatusWindow); snprintf(buf, sizeof(buf), "%04x", m_SNR); m_Osd->Text(OSDSTATUSWIN_X(2), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow); @@ -137,12 +138,12 @@ void cFemonOsd::DrawStatusWindow(void) m_Osd->Text(OSDSTATUSWIN_X(4), OSDSTATUSWIN_Y(offset), "UNC:", clrWhite, clrBackground, m_StatusWindow); snprintf(buf, sizeof(buf), "%08x", m_UNC); m_Osd->Text(OSDSTATUSWIN_X(5), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow); - snprintf(buf, sizeof(buf), "%s:", tr("Audio")); + snprintf(buf, sizeof(buf), "%s:", (m_Receiver && m_Receiver->AC3Valid()) ? tr("AC-3") : tr("Audio")); m_Osd->Text(OSDSTATUSWIN_X(6), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow); - if (m_Receiver) snprintf(buf, sizeof(buf), "%.0f %s", m_Receiver->AudioBitrate(), tr("kbit/s")); + if (m_Receiver) snprintf(buf, sizeof(buf), "%.0f %s", m_Receiver->AC3Valid() ? m_Receiver->AC3Bitrate() : m_Receiver->AudioBitrate(), tr("kbit/s")); else snprintf(buf, sizeof(buf), "--- %s", tr("kbit/s")); m_Osd->Text(OSDSTATUSWIN_X(7), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDSTATUSWIN_XC(1,tr("LOCK")), OSDSTATUSWIN_Y(offset), tr("LOCK"), (m_FrontendStatus & FE_HAS_LOCK) ? clrYellow : clrBlack, clrBackground, m_StatusWindow); m_Osd->Text(OSDSTATUSWIN_XC(2,tr("SIGNAL")), OSDSTATUSWIN_Y(offset), tr("SIGNAL"), (m_FrontendStatus & FE_HAS_SIGNAL) ? clrYellow : clrBlack, clrBackground, m_StatusWindow); m_Osd->Text(OSDSTATUSWIN_XC(3,tr("CARRIER")), OSDSTATUSWIN_Y(offset), tr("CARRIER"),(m_FrontendStatus & FE_HAS_CARRIER)? clrYellow : clrBlack, clrBackground, m_StatusWindow); @@ -181,7 +182,7 @@ void cFemonOsd::DrawInfoWindow(void) m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Ppid"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Ppid()); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Apid1"), clrWhite, clrBackground, m_InfoWindow); value = channel->Apid2(); if (value) snprintf(buf, sizeof(buf), "%d, %d", channel->Apid1(), value); @@ -192,14 +193,14 @@ void cFemonOsd::DrawInfoWindow(void) if (value) snprintf(buf, sizeof(buf), "%d, %d", channel->Dpid1(), value); else snprintf(buf, sizeof(buf), "%d", channel->Dpid1()); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("CA"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Ca()); m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Tpid"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Tpid()); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Sid"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Sid()); m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); @@ -207,7 +208,7 @@ void cFemonOsd::DrawInfoWindow(void) m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Nid"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Nid()); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Tid"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Tid()); m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); @@ -215,12 +216,12 @@ void cFemonOsd::DrawInfoWindow(void) snprintf(buf, sizeof(buf), "%d", channel->Rid()); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); #endif - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; switch (m_FrontendInfo.type) { case FE_QPSK: snprintf(buf, sizeof(buf), "%s #%d - %s", tr("Satellite Card"), cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name); m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow); value = channel->Frequency(); while (value > 20000) value /= 1000; @@ -229,14 +230,14 @@ void cFemonOsd::DrawInfoWindow(void) m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Source"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%s", cSource::ToString(channel->Source())); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Srate"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Srate()); m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Polarization"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%c", toupper(channel->Polarization())); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow); value = channel->Inversion(); if (value == INVERSION_OFF) snprintf(buf, sizeof(buf), tr("Off")); @@ -261,7 +262,7 @@ void cFemonOsd::DrawInfoWindow(void) case FE_QAM: snprintf(buf, sizeof(buf), "%s #%d - %s", tr("Cable Card"), cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name); m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow); value = channel->Frequency(); while (value > 20000) value /= 1000; @@ -270,7 +271,7 @@ void cFemonOsd::DrawInfoWindow(void) m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Source"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%s", cSource::ToString(channel->Source())); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Srate"), clrWhite, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "%d", channel->Srate()); m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); @@ -284,7 +285,7 @@ void cFemonOsd::DrawInfoWindow(void) else if (value == QAM_256) snprintf(buf, sizeof(buf), "QAM 256"); else /*QAM_AUTO*/ snprintf(buf, sizeof(buf), "QAM %s", tr("Auto")); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow); value = channel->Inversion(); if (value == INVERSION_OFF) snprintf(buf, sizeof(buf), tr("Off")); @@ -309,7 +310,7 @@ void cFemonOsd::DrawInfoWindow(void) default: snprintf(buf, sizeof(buf), "%s #%d - %s", tr("Terrestial Card"), cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name); m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow); value = channel->Frequency(); while (value > 20000) value /= 1000; @@ -321,7 +322,7 @@ void cFemonOsd::DrawInfoWindow(void) else if (value == TRANSMISSION_MODE_8K) snprintf(buf, sizeof(buf), "8K"); else /*TRANSMISSION_MODE_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto")); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text( OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bandwidth"), clrWhite, clrBackground, m_InfoWindow); value = channel->Bandwidth(); if (value == BANDWIDTH_8_MHZ) snprintf(buf, sizeof(buf), "8 %s", tr("MHz")); @@ -339,7 +340,7 @@ void cFemonOsd::DrawInfoWindow(void) else if (value == QAM_256) snprintf(buf, sizeof(buf), "QAM 256"); else /*QAM_AUTO*/ snprintf(buf, sizeof(buf), "QAM %s", tr("Auto")); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow); value = channel->Inversion(); if (value == INVERSION_OFF) snprintf(buf, sizeof(buf), tr("Off")); @@ -371,7 +372,7 @@ void cFemonOsd::DrawInfoWindow(void) else /*FEC_AUTO*/ snprintf(buf2, sizeof(buf2), " - %s", tr("Auto")); strncat(buf, buf2, sizeof(buf)); m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Hierarchy"), clrWhite, clrBackground, m_InfoWindow); value = channel->Hierarchy(); if (value == HIERARCHY_NONE) snprintf(buf, sizeof(buf), tr("None")); @@ -392,19 +393,19 @@ void cFemonOsd::DrawInfoWindow(void) } } else if (m_DisplayMode == modeStream) { - m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrBackground); - m_Osd->Fill(0, OSDINFOWIN_Y(offset), OSDWIDTH, OSDINFOWIN_Y(offset+cOsd::LineHeight()-1), clrWhite); + m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrBackground, m_InfoWindow); + m_Osd->Fill(0, OSDINFOWIN_Y(offset), OSDWIDTH, OSDINFOWIN_Y(offset+cOsd::LineHeight()-1), clrWhite, m_InfoWindow); m_Osd->Text( OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Stream Information"), clrBackground, clrWhite, m_InfoWindow); offset += cOsd::LineHeight(); m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Video Stream"), clrYellow, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "#%d", channel->Vpid()); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bitrate"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) snprintf(buf, sizeof(buf), "%.2f %s (%.2f %s)", m_Receiver->VideoStreamBitrate(), tr("Mbit/s"), m_Receiver->VideoBitrate(), tr("Mbit/s")); else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Aspect Ratio"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) { value = m_Receiver->VideoAspectRatio(); @@ -416,12 +417,12 @@ void cFemonOsd::DrawInfoWindow(void) } else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frame Rate"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) snprintf(buf, sizeof(buf), "%.2f %s", m_Receiver->VideoFrameRate(), tr("Hz")); else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Video Format"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) { value = m_Receiver->VideoFormat(); @@ -431,16 +432,16 @@ void cFemonOsd::DrawInfoWindow(void) } else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Resolution"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) snprintf(buf, sizeof(buf), "%d x %d", m_Receiver->VideoHorizontalSize(), m_Receiver->VideoVerticalSize()); else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Audio Stream"), clrYellow, clrBackground, m_InfoWindow); snprintf(buf, sizeof(buf), "#%d", channel->Apid1()); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bitrate"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) { dvalue = m_Receiver->AudioStreamBitrate(); @@ -450,20 +451,113 @@ void cFemonOsd::DrawInfoWindow(void) } else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("MPEG Layer"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) snprintf(buf, sizeof(buf), "%d", m_Receiver->AudioMPEGLayer()); else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); - offset += cOsd::LineHeight() - 2; + offset += cOsd::LineHeight() - DELTA; m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Sampling Frequency"), clrWhite, clrBackground, m_InfoWindow); if (m_Receiver) { - value = m_Receiver->AudioSamplingFreq(); + value = m_Receiver->AudioSamplingFreq(); if (value == FR_RESERVED) snprintf(buf, sizeof(buf), "%s", tr("reserved")); else snprintf(buf, sizeof(buf), "%.1f %s", (value / 1000.0), tr("kHz")); } else snprintf(buf, sizeof(buf), "---"); m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + } + else if (m_DisplayMode == modeAC3) { + m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrBackground, m_InfoWindow); + m_Osd->Fill(0, OSDINFOWIN_Y(offset), OSDWIDTH, OSDINFOWIN_Y(offset+cOsd::LineHeight()-1), clrWhite, m_InfoWindow); + snprintf(buf, sizeof(buf), "%s - %s #%d", tr("Stream Information"), tr("AC-3 Stream"), channel->Dpid1()); + m_Osd->Text( OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrBackground, clrWhite, m_InfoWindow); + offset += cOsd::LineHeight(); + if (m_Receiver && m_Receiver->AC3Valid()) { + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bitrate"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%.0f %s (%0.f %s)", m_Receiver->AC3StreamBitrate(), tr("kbit/s"), m_Receiver->AC3Bitrate(), tr("kbit/s")); + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Sampling Frequency"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%.1f %s", m_Receiver->AC3SamplingFreq() / 1000., tr("kHz")); + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frame Size"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", m_Receiver->AC3FrameSize()); + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bit Stream Mode"), clrWhite, clrBackground, m_InfoWindow); + switch (m_Receiver->AC3BitStreamMode()) { + case 0: snprintf(buf, sizeof(buf), tr("Complete Main (CM)")); break; + case 1: snprintf(buf, sizeof(buf), tr("Music and Effects (ME)")); break; + case 2: snprintf(buf, sizeof(buf), tr("Visually Impaired (VI)")); break; + case 3: snprintf(buf, sizeof(buf), tr("Hearing Impaired (HI)")); break; + case 4: snprintf(buf, sizeof(buf), tr("Dialogue (D)")); break; + case 5: snprintf(buf, sizeof(buf), tr("Commentary (C)")); break; + case 6: snprintf(buf, sizeof(buf), tr("Emergency (E)")); break; + case 7: (m_Receiver->AC3AudioCodingMode() == 1) ? snprintf(buf, sizeof(buf), tr("Voice Over (VO)")) : snprintf(buf, sizeof(buf), tr("Karaoke")); break; + default: snprintf(buf, sizeof(buf), "---"); + } + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Audio Coding Mode"), clrWhite, clrBackground, m_InfoWindow); + if (m_Receiver->AC3BitStreamMode() != 7) { + switch (m_Receiver->AC3AudioCodingMode()) { + case 0: snprintf(buf, sizeof(buf), "1+1 - %s, %s", tr("Ch1"), tr("Ch2")); break; + case 1: snprintf(buf, sizeof(buf), "1/0 - %s", tr("C")); break; + case 2: snprintf(buf, sizeof(buf), "2/0 - %s, %s", tr("L"), tr("R")); break; + case 3: snprintf(buf, sizeof(buf), "3/0 - %s, %s, %s", tr("L"), tr("C"), tr("R")); break; + case 4: snprintf(buf, sizeof(buf), "2/1 - %s, %s, %s", tr("L"), tr("R"), tr("S")); break; + case 5: snprintf(buf, sizeof(buf), "3/1 - %s, %s, %s, %s", tr("L"), tr("C"), tr("R"), tr("S")); break; + case 6: snprintf(buf, sizeof(buf), "2/2 - %s, %s, %s, %s", tr("L"), tr("R"), tr("SL"), tr("SR")); break; + case 7: snprintf(buf, sizeof(buf), "3/2 - %s, %s, %s, %s, %s", tr("L"), tr("C"), tr("R"), tr("SL"), tr("SR")); break; + default: snprintf(buf, sizeof(buf), "---"); + } + } + else snprintf(buf, sizeof(buf), "---"); + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Center Mix Level"), clrWhite, clrBackground, m_InfoWindow); + switch (m_Receiver->AC3CenterMixLevel()) { + case CML_MINUS_3dB: snprintf(buf, sizeof(buf), "-3.0 %s", tr("dB")); break; + case CML_MINUS_4_5dB: snprintf(buf, sizeof(buf), "-4.5 %s", tr("dB")); break; + case CML_MINUS_6dB: snprintf(buf, sizeof(buf), "-6.0 %s", tr("dB")); break; + case CML_RESERVED: snprintf(buf, sizeof(buf), "%s", tr("reserved")); break; + default: snprintf(buf, sizeof(buf), "---"); + } + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Surround Mix Level"), clrWhite, clrBackground, m_InfoWindow); + switch (m_Receiver->AC3SurroundMixLevel()) { + case SML_MINUS_3dB: snprintf(buf, sizeof(buf), "-3 %s", tr("dB")); break; + case SML_MINUS_6dB: snprintf(buf, sizeof(buf), "-6 %s", tr("dB")); break; + case SML_0_dB: snprintf(buf, sizeof(buf), "0 %s", tr("dB")); break; + case SML_RESERVED: snprintf(buf, sizeof(buf), "%s", tr("reserved")); break; + default: snprintf(buf, sizeof(buf), "---"); + } + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Dolby Surround Mode"), clrWhite, clrBackground, m_InfoWindow); + switch (m_Receiver->AC3DolbySurroundMode()) { + case DSM_NOT_INDICATED: snprintf(buf, sizeof(buf), "%s", tr("not indicated")); break; + case DSM_NOT_DOLBYSURROUND: snprintf(buf, sizeof(buf), "%s", tr("Off")); break; + case DSM_DOLBYSURROUND: snprintf(buf, sizeof(buf), "%s", tr("On")); break; + case DSM_RESERVED: snprintf(buf, sizeof(buf), "%s", tr("reserved")); break; + default: snprintf(buf, sizeof(buf), "---"); + } + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Low Frequency Effects"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%s", m_Receiver->AC3LfeOn() ? tr("On") : tr("Off")); + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Dialogue Normalization"), clrWhite, clrBackground, m_InfoWindow); + value = m_Receiver->AC3DialogLevel(); + if (value > 0) snprintf(buf, sizeof(buf), "-%d %s", value, tr("dB")); + else snprintf(buf, sizeof(buf), "---"); + m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow); + offset += cOsd::LineHeight() - DELTA; + } } else /* modeBasic */ { m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrTransparent, m_InfoWindow); @@ -536,8 +630,8 @@ void cFemonOsd::Show(void) if (m_Receiver) delete m_Receiver; if (femonConfig.analyzestream) { - int channelNumber = cDevice::CurrentChannel(); - m_Receiver = new cFemonReceiver(Channels.GetByNumber(channelNumber)->Ca(), Channels.GetByNumber(channelNumber)->Vpid(), Channels.GetByNumber(channelNumber)->Apid1()); + cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel()); + m_Receiver = new cFemonReceiver(channel->Ca(), channel->Vpid(), channel->Apid1(), channel->Dpid1()); cDevice::ActualDevice()->AttachReceiver(m_Receiver); } Start(); @@ -568,8 +662,8 @@ void cFemonOsd::ChannelSwitch(const cDevice * device, int channelNumber) if (m_Receiver) delete m_Receiver; if (femonConfig.analyzestream) { - channelNumber = cDevice::CurrentChannel(); - m_Receiver = new cFemonReceiver(Channels.GetByNumber(channelNumber)->Ca(), Channels.GetByNumber(channelNumber)->Vpid(), Channels.GetByNumber(channelNumber)->Apid1()); + cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel()); + m_Receiver = new cFemonReceiver(channel->Ca(), channel->Vpid(), channel->Apid1(), channel->Dpid1()); cDevice::ActualDevice()->AttachReceiver(m_Receiver); } } @@ -640,7 +734,9 @@ eOSState cFemonOsd::ProcessKey(eKeys Key) } break; case kOk: - if (++m_DisplayMode >= modeMaxNumber) m_DisplayMode = 0; // toggle between display modes + // toggle between display modes + if (++m_DisplayMode == modeAC3 && !Channels.GetByNumber(cDevice::CurrentChannel())->Dpid1()) m_DisplayMode++; + if (m_DisplayMode >= modeMaxNumber) m_DisplayMode = 0; DrawInfoWindow(); break; default: diff --git a/femonreceiver.c b/femonreceiver.c index 3402ac3..d171c80 100644 --- a/femonreceiver.c +++ b/femonreceiver.c @@ -16,17 +16,19 @@ #define PAYLOAD 0x10 #define PTS_DTS_FLAGS 0xC0 -cFemonReceiver::cFemonReceiver(int Ca, int Vpid, int Apid) +cFemonReceiver::cFemonReceiver(int Ca, int Vpid, int Apid, int Dpid) #if VDRVERSNUM >= 10300 -:cReceiver(Ca, -1, 2, Vpid, Apid), cThread("femon receiver") +:cReceiver(Ca, -1, 3, Vpid, Apid, Dpid), cThread("femon receiver") #else -:cReceiver(Ca, -1, 2, Vpid, Apid) +:cReceiver(Ca, -1, 3, Vpid, Apid, Dpid) #endif { //printf("cFemonReceiver::cFemonReceiver()\n"); m_Active = false; m_VideoPid = Vpid; m_AudioPid = Apid; + m_AC3Pid = Dpid; + m_VideoValid = false; m_VideoPacketCount = 0; m_VideoHorizontalSize = 0; m_VideoVerticalSize = 0; @@ -35,13 +37,26 @@ cFemonReceiver::cFemonReceiver(int Ca, int Vpid, int Apid) m_VideoFrameRate = 0.0; m_VideoStreamBitrate = 0.0; m_VideoBitrate = 0.0; + m_AudioValid = false; m_AudioPacketCount = 0; m_AudioStreamBitrate = -2.0; m_AudioBitrate = 0.0; m_AudioSamplingFreq = -1; m_AudioMPEGLayer = 0; m_AudioBitrate = 0.0; - + m_AC3Valid = false; + m_AC3PacketCount = 0; + m_AC3StreamBitrate = 0; + m_AC3SamplingFreq = 0; + m_AC3Bitrate = 0; + m_AC3FrameSize = 0; + m_AC3BitStreamMode = FR_NOTVALID; + m_AC3AudioCodingMode = FR_NOTVALID; + m_AC3CenterMixLevel = FR_NOTVALID; + m_AC3SurroundMixLevel = FR_NOTVALID; + m_AC3DolbySurroundMode = FR_NOTVALID; + m_AC3LfeOn = false; + m_AC3DialogLevel = FR_NOTVALID; } cFemonReceiver::~cFemonReceiver(void) @@ -53,29 +68,29 @@ cFemonReceiver::~cFemonReceiver(void) } } -/* the following function originates from libdvbmpeg: */ +/* The following function originates from libdvbmpeg: */ void cFemonReceiver::GetVideoInfo(uint8_t *mbuf, int count) { //printf("cFemonReceiver::GetVideoInfo()\n"); uint8_t *headr; int found = 0; int c = 0; - while (found < 4 && c + 4 < count) { + m_VideoValid = false; + while ((found < 4) && ((c + 4) < count)) { uint8_t *b; b = mbuf + c; - if (b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 && b[3] == 0xb3) + if ((b[0] == 0x00) && (b[1] == 0x00) && (b[2] == 0x01) && (b[3] == 0xb3)) found = 4; else c++; } - if (!found) return; - c += 4; - if (c + 12 >= count) return; - headr = mbuf + c; - m_VideoHorizontalSize = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); - m_VideoVerticalSize = ((headr[1] &0x0F) << 8) | (headr[2]); + if ((!found) || ((c + 16) >= count)) return; + m_VideoValid = true; + headr = mbuf + c + 4; + m_VideoHorizontalSize = ((headr[1] & 0xF0) >> 4) | (headr[0] << 4); + m_VideoVerticalSize = ((headr[1] & 0x0F) << 8) | (headr[2]); int sw = (int)((headr[3] & 0xF0) >> 4); - switch( sw ){ + switch ( sw ){ case 1: m_VideoAspectRatio = AR_1_1; break; @@ -89,15 +104,14 @@ void cFemonReceiver::GetVideoInfo(uint8_t *mbuf, int count) m_VideoAspectRatio = AR_2_21_1; break; case 5 ... 15: + default: m_VideoAspectRatio = AR_RESERVED; break; - default: - return; } sw = (int)(headr[3] & 0x0F); switch ( sw ) { case 1: - m_VideoFrameRate = 24000/1001.0; + m_VideoFrameRate = 24000 / 1001.0; m_VideoFormat = VF_UNKNOWN; break; case 2: @@ -109,7 +123,7 @@ void cFemonReceiver::GetVideoInfo(uint8_t *mbuf, int count) m_VideoFormat = VF_PAL; break; case 4: - m_VideoFrameRate = 30000/1001.0; + m_VideoFrameRate = 30000 / 1001.0; m_VideoFormat = VF_NTSC; break; case 5: @@ -124,6 +138,15 @@ void cFemonReceiver::GetVideoInfo(uint8_t *mbuf, int count) m_VideoFrameRate = 60.0; m_VideoFormat = VF_NTSC; break; + case 8: + m_VideoFrameRate = 60000 / 1001.0; + m_VideoFormat = VF_NTSC; + break; + case 9 ... 15: + default: + m_VideoFrameRate = 0; + m_VideoFormat = VF_UNKNOWN; + break; } m_VideoStreamBitrate = 400 * (((headr[4] << 10) & 0x0003FC00UL) | ((headr[5] << 2) & 0x000003FCUL) | (((headr[6] & 0xC0) >> 6) & 0x00000003UL)) / 1000000.0; } @@ -135,9 +158,10 @@ static unsigned int bitrates[3][16] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0} }; -static unsigned int samplerates[4] = {441, 480, 320, 0}; +static unsigned int samplerates[4] = +{441, 480, 320, 0}; -/* the following function originates from libdvbmpeg: */ +/* The following function originates from libdvbmpeg: */ void cFemonReceiver::GetAudioInfo(uint8_t *mbuf, int count) { //printf("cFemonReceiver::GetAudioInfo()\n"); @@ -145,15 +169,16 @@ void cFemonReceiver::GetAudioInfo(uint8_t *mbuf, int count) int found = 0; int c = 0; int tmp = 0; - while (!found && c < count) { + m_AudioValid = false; + while (!found && (c < count)) { uint8_t *b = mbuf + c; - if (b[0] == 0xff && (b[1] & 0xf8) == 0xf8) + if ((b[0] == 0xff) && ((b[1] & 0xf8) == 0xf8)) found = 1; else c++; } - if (!found) return; - if (c + 3 >= count) return; + if ((!found) || ((c + 3) >= count)) return; + m_AudioValid = true; headr = mbuf + c; m_AudioMPEGLayer = 4 - ((headr[1] & 0x06) >> 1); tmp = bitrates[(3 - ((headr[1] & 0x06) >> 1))][(headr[2] >> 4)] * 1000; @@ -170,6 +195,65 @@ void cFemonReceiver::GetAudioInfo(uint8_t *mbuf, int count) m_AudioSamplingFreq = tmp; } +static unsigned int ac3_bitrates[32] = +{32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static unsigned int ac3_freq[4] = +{480, 441, 320, 0}; + +static unsigned int ac3_frames[3][32] = +{ + {64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {69, 87, 104, 121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114, 1253, 1393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960, 1152, 1344, 1536, 1728, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +/* +** AC3 Audio Header: http://www.atsc.org/standards/a_52a.pdf +** The following function originates from libdvbmpeg: +*/ +void cFemonReceiver::GetAC3Info(uint8_t *mbuf, int count) +{ + uint8_t *headr; + int found = 0; + int c = 0; + uint8_t frame; + m_AC3Valid = false; + while (!found && (c < count)) { + uint8_t *b = mbuf + c; + if ((b[0] == 0x0b) && (b[1] == 0x77)) + found = 1; + else + c++; + } + if ((!found) || ((c + 5) >= count)) return; + m_AC3Valid = true; + headr = mbuf + c + 2; + frame = (headr[2] & 0x3f); + m_AC3StreamBitrate = ac3_bitrates[frame >> 1]; + int fr = (headr[2] & 0xc0 ) >> 6; + m_AC3SamplingFreq = ac3_freq[fr] * 100; + m_AC3FrameSize = ac3_frames[fr][frame >> 1]; + if ((frame & 1) && (fr == 1)) m_AC3FrameSize++; + m_AC3FrameSize <<= 1; + m_AC3BitStreamMode = (headr[3] & 7); + m_AC3AudioCodingMode = (headr[4] & 0xE0) >> 5; + if ((m_AC3AudioCodingMode & 0x01) && (m_AC3AudioCodingMode != 0x01)) // if 3 front channels + m_AC3CenterMixLevel = (headr[4] & 0x18) >> 3; + else + m_AC3CenterMixLevel = FR_NOTVALID; + if (m_AC3AudioCodingMode & 0x04) // if a surround channel exists + m_AC3SurroundMixLevel = (headr[4] & 0x06) >> 1; + else + m_AC3SurroundMixLevel = FR_NOTVALID; + if (m_AC3AudioCodingMode == 0x02) // if in 2/0 mode + m_AC3DolbySurroundMode = ((headr[4] & 1) << 1) | ((headr[5] & 0x80) >> 7); + else + m_AC3DolbySurroundMode = FR_NOTVALID; + m_AC3LfeOn = (headr[5] & 0x40) >> 6; + m_AC3DialogLevel = (headr[5] & 0x3e) >> 1; +} + void cFemonReceiver::Activate(bool On) { //printf("cFemonReceiver::Activate()\n"); @@ -188,6 +272,9 @@ void cFemonReceiver::Receive(uchar *Data, int Length) else if (pid == m_AudioPid) { m_AudioPacketCount++; } + else if (pid == m_AC3Pid) { + m_AC3PacketCount++; + } /* the following originates from libdvbmpeg: */ if (!(Data[3] & PAYLOAD)) { return; @@ -204,9 +291,12 @@ void cFemonReceiver::Receive(uchar *Data, int Length) if (pid == m_VideoPid) { GetVideoInfo(pay, l); } - if (pid == m_AudioPid) { + else if (pid == m_AudioPid) { GetAudioInfo(pay, l); } + else if (pid == m_AC3Pid) { + GetAC3Info(pay, l); + } } } /* end */ @@ -226,6 +316,8 @@ void cFemonReceiver::Action(void) m_VideoPacketCount = 0; m_AudioBitrate = (8.0 * 184.0 * m_AudioPacketCount) / (femonConfig.calcinterval * 100.0); m_AudioPacketCount = 0; + m_AC3Bitrate = (8.0 * 184.0 * m_AC3PacketCount) / (femonConfig.calcinterval * 100.0); + m_AC3PacketCount = 0; usleep(100000L * femonConfig.calcinterval); } #if (VDRVERSNUM < 10300) diff --git a/femonreceiver.h b/femonreceiver.h index 5d2bdd9..1b0b117 100644 --- a/femonreceiver.h +++ b/femonreceiver.h @@ -26,29 +26,68 @@ enum eAspectRatio { AR_2_21_1 = 233, }; -#define FR_RESERVED -1 -#define FR_FREE -2 +enum eCenterMixLevel { + CML_MINUS_3dB = 0, + CML_MINUS_4_5dB = 1, + CML_MINUS_6dB = 2, + CML_RESERVED = 3, + }; + +enum eSurroundMixLevel { + SML_MINUS_3dB = 0, + SML_MINUS_6dB = 1, + SML_0_dB = 2, + SML_RESERVED = 3, + }; + +enum eDolbySurroundMode { + DSM_NOT_INDICATED = 0, + DSM_NOT_DOLBYSURROUND = 1, + DSM_DOLBYSURROUND = 2, + DSM_RESERVED = 3, + }; + +#define FR_RESERVED -1 +#define FR_FREE -2 +#define FR_NOTVALID -3 class cFemonReceiver : public cReceiver, public cThread { private: - bool m_Active; - int m_VideoPid; - int m_AudioPid; - int m_VideoPacketCount; - int m_VideoHorizontalSize; - int m_VideoVerticalSize; - int m_VideoAspectRatio; - int m_VideoFormat; + bool m_Active; + int m_VideoPid; + int m_AudioPid; + int m_AC3Pid; + bool m_VideoValid; + int m_VideoPacketCount; + int m_VideoHorizontalSize; + int m_VideoVerticalSize; + int m_VideoAspectRatio; + int m_VideoFormat; double m_VideoFrameRate; double m_VideoStreamBitrate; double m_VideoBitrate; - int m_AudioPacketCount; + bool m_AudioValid; + int m_AudioPacketCount; double m_AudioStreamBitrate; double m_AudioBitrate; - int m_AudioSamplingFreq; - int m_AudioMPEGLayer; - void GetVideoInfo(uint8_t *mbuf, int count); - void GetAudioInfo(uint8_t *mbuf, int count); + int m_AudioSamplingFreq; + int m_AudioMPEGLayer; + bool m_AC3Valid; + int m_AC3PacketCount; + double m_AC3Bitrate; + int m_AC3FrameSize; + int m_AC3SamplingFreq; + int m_AC3StreamBitrate; + int m_AC3BitStreamMode; + int m_AC3AudioCodingMode; + int m_AC3CenterMixLevel; + int m_AC3SurroundMixLevel; + int m_AC3DolbySurroundMode; + bool m_AC3LfeOn; + int m_AC3DialogLevel; + void GetVideoInfo(uint8_t *mbuf, int count); + void GetAudioInfo(uint8_t *mbuf, int count); + void GetAC3Info(uint8_t *mbuf, int count); protected: virtual void Activate(bool On); @@ -56,9 +95,10 @@ protected: virtual void Action(void); public: - cFemonReceiver(int Ca, int Vpid, int Apid); + cFemonReceiver(int Ca, int Vpid, int Apid, int Dpid); virtual ~cFemonReceiver(); + bool VideoValid(void) { return m_VideoValid; }; // boolean int VideoHorizontalSize(void) { return m_VideoHorizontalSize; }; // pixels int VideoVerticalSize(void) { return m_VideoVerticalSize; }; // pixels int VideoAspectRatio(void) { return m_VideoAspectRatio; }; // eAspectRatio @@ -67,10 +107,26 @@ public: double VideoStreamBitrate(void) { return m_VideoStreamBitrate; }; // Mbit/s double VideoBitrate(void) { return m_VideoBitrate; }; // Mbit/s + bool AudioValid(void) { return m_AudioValid; }; // boolean int AudioMPEGLayer(void) { return m_AudioMPEGLayer; }; // layer number int AudioSamplingFreq(void) { return m_AudioSamplingFreq; }; // Hz double AudioStreamBitrate(void) { return m_AudioStreamBitrate; }; // kbit/s double AudioBitrate(void) { return m_AudioBitrate; }; // kbit/s + + bool AC3Valid(void) { return m_AC3Valid; }; // boolean + int AC3SamplingFreq(void) { return m_AC3SamplingFreq; }; // Hz + double AC3StreamBitrate(void) { return m_AC3StreamBitrate; }; // kbit/s + double AC3Bitrate(void) { return m_AC3Bitrate; }; // kbit/s + int AC3FrameSize(void) { return m_AC3FrameSize; }; // Bytes + int AC3BitStreamMode(void) { return m_AC3BitStreamMode; }; // 0..7 + int AC3AudioCodingMode(void) { return m_AC3AudioCodingMode; }; // 0..7 + bool AC3_2_0(void) { return m_AC3AudioCodingMode == 2; }; // DD 2.0 + bool AC3_5_1(void) { return m_AC3AudioCodingMode == 7; }; // DD 5.1 + int AC3CenterMixLevel(void) { return m_AC3CenterMixLevel; }; // eCenterMixLevel + int AC3SurroundMixLevel(void) { return m_AC3SurroundMixLevel; }; // eSurroundMixLevel + int AC3DolbySurroundMode(void) { return m_AC3DolbySurroundMode; }; // eDolbySurroundMode + bool AC3LfeOn(void) { return m_AC3LfeOn; }; // boolean + int AC3DialogLevel(void) { return m_AC3DialogLevel; }; // -dB }; #endif //__FEMONRECEIVER_H