diff options
-rw-r--r-- | CONTRIBUTORS | 23 | ||||
-rw-r--r-- | HISTORY | 41 | ||||
-rw-r--r-- | MANUAL | 3 | ||||
-rw-r--r-- | PLUGINS.html | 59 | ||||
-rw-r--r-- | channels.c | 4 | ||||
-rw-r--r-- | channels.conf | 8 | ||||
-rw-r--r-- | config.c | 5 | ||||
-rw-r--r-- | config.h | 7 | ||||
-rw-r--r-- | device.c | 115 | ||||
-rw-r--r-- | device.h | 13 | ||||
-rw-r--r-- | dvbdevice.c | 6 | ||||
-rw-r--r-- | dvbspu.c | 9 | ||||
-rw-r--r-- | i18n.c | 81 | ||||
-rw-r--r-- | menu.c | 13 | ||||
-rwxr-xr-x | newplugin | 8 | ||||
-rw-r--r-- | pat.c | 10 | ||||
-rw-r--r-- | player.h | 4 | ||||
-rw-r--r-- | plugin.c | 30 | ||||
-rw-r--r-- | plugin.h | 8 | ||||
-rw-r--r-- | recording.c | 4 | ||||
-rw-r--r-- | remux.c | 260 | ||||
-rw-r--r-- | timers.c | 4 | ||||
-rw-r--r-- | tools.c | 10 | ||||
-rw-r--r-- | tools.h | 4 | ||||
-rw-r--r-- | vdr.c | 5 |
25 files changed, 494 insertions, 240 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 48b54d4..0c29e35 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -190,10 +190,11 @@ Stefan Huelswitt <huels@iname.com> for fixing handling of pmAudioOnlyBlack for pointing out possible race conditions in handling childTid in cThread for fixing a possible race condition in cDevice::Action() and cTSBuffer::Action() + for reporting several memory leaks that were introduced through the use of cString + for adding MPEG1 replay capability to cPesAssembler Ulrich Röder <roeder@efr-net.de> - for pointing out that there are channels that have a symbol rate higher than - 27500 + for pointing out that there are channels that have a symbol rate higher than 27500 for his support in keeping the Premiere World channels up to date in 'channels.conf' Mel Schächner <schaechner@yahoo.com> @@ -266,6 +267,11 @@ Werner Fink <werner@suse.de> overhead in the firmware for a patch that was used as a base for implementing a modified PES packet handling in order to play AC3 audio over full featured DVB cards + for pointing out an error in masking SubStreamType in cDevice::PlayPesPacket() + for pointing out that the "pre 1.3.19" compatibility mode for old Dolby Digital + recordings can be triggered in the default branch + for pointing out that pesAssembler->Reset() needs to be called between subsequent + Transfer Modes Rolf Hakenes <hakenes@hippomi.de> for providing 'libdtv' and adapting the EIT mechanisms to it @@ -747,6 +753,11 @@ Sascha Volkenandt <sascha@akv-soft.de> for reporting a bug in cChannel::SetName() in case only the ShortName or Provider has changed for fixing a possible recursion in cControl::Shutdown() + for reporting that the "Audio" menu is not displayed with the "Green" button from + the "Main" menu in case there is only one audio track + for reporting a problem when starting replay of a recording that has no Dolby + Digital audio after switching to a channel that has DD and selecting the DD audio + track Malcolm Caldwell <malcolm.caldwell@ntu.edu.au> for modifying LOF handling to allow for C-band reception @@ -793,6 +804,7 @@ Benjamin Harling <benjamin.harling@web.de> Christian Jacobsen <christian.jacobsen@stageholding.de> for making the LIRC interface skip keys that come in too fast for reporting a problem in handling the '-E' options in version 1.3.18 + for reporting a problem in case a station defines all 32 audio PIDs Andreas Mair <Andreas.Mair@linogate.com> for reporting a short display of the main menu if a plugin displays its own OSD and @@ -800,6 +812,7 @@ Andreas Mair <Andreas.Mair@linogate.com> Olivier Jacques <jacquesolivier@hotmail.com>) for translating OSD texts to the French language + for implementing the setup option "OSD/Channel info time" Kai Moeller <moeller.ki@gmx.de> for reporting a double call to MainMenuAction() of a plugin if invoked via a hotkey @@ -911,6 +924,7 @@ Reinhard Nissl <rnissl@gmx.de> for implementing cDolbyRepacker for better handling of Dolby Digital PES packets for extending some buffer sizes to allow handling HDTV streams for adding substream handling to cDolbyRepacker + for modifying cDolbyRepacker to make sure PES packets don't exceed the requested length Richard Robson <richard_robson@beeb.net> for reporting freezing replay if a timer starts while in Transfer Mode from the @@ -1116,6 +1130,7 @@ Marco Schlüßler <marco@lordzodiac.de> for a patch that implements substream handling into cDevice::PlayPesPacket() for pointing out that PlayPes(NULL, 0) needs to be called in cTransfer::Action() when clearing the transfer buffer to avoid overflows + for adding CMD_SPU_CHG_COLCON to cDvbSpuDecoder::setTime() Jürgen Schmitz <j.schmitz@web.de> for reporting a bug in displaying the current channel when switching via the SVDRP @@ -1231,3 +1246,7 @@ Walter Koch <koch@u32.de> Rolf Groppe <rolf@groppe.de> for suggesting to fall back to 'stereo' when switching channels in case the user had switched to 'left' or 'right' + +Wolfgang Rohdewald <wolfgang@rohdewald.de> + for pointing out that primaryDevice = NULL should be done before deleting the devices + in cDevice::Shutdown() @@ -3332,3 +3332,44 @@ Video Disk Recorder Revision History cDolbyRepacker). - Added PlayPes(NULL, 0) to cTransfer::Action() when clearing the transfer buffer to avoid overflows (thanks to Marco Schlüßler for pointing this out). + +2005-02-06: Version 1.3.20 + +- Fixed displaying the "Audio" menu with the "Green" button from the "Main" menu + in case there is only one audio track (thanks to Sascha Volkenandt for reporting + this one). +- Now setting primaryDevice = NULL before deleting the devices in cDevice::Shutdown() + to avoid problems in case other threads access it (thanks to Wolfgang Rohdewald for + pointing this out). +- Fixed a buffer overflow in case a station defines all 32 audio PIDs (thanks to + Christian Jacobsen for reporting this one). +- Fixed masking SubStreamType in cDevice::PlayPesPacket() (thanks to Werner Fink + for pointing out this one). +- The new function cPlugin::Stop() shall be used to stop any background activities + of a plugin. Previously this was done in the plugin's desctructor, but it is + better to do this in a dedicated function that can be called early when shutting + down. +- Moved the call to SetAudioChannel(0) into cDevice::ClrAvailableTracks() to have it + executed also when starting a replay. +- Completed the Danish OSD texts (thanks to Mogens Elneff). +- Completed the French OSD texts (thanks to Olivier Jacques). +- The new setup option "OSD/Channel info time" can be used to define the time after + which the channel display is removed if no key has been pressed (thanks to + Olivier Jacques). +- Modified cDolbyRepacker to make sure PES packets don't exceed the requested length + (thanks to Reinhard Nissl). +- Fixed several memory leaks that were introduced through the use of cString (thanks + to Stefan Huelswitt for reporting these). +- Added CMD_SPU_CHG_COLCON to cDvbSpuDecoder::setTime() (thanks to Marco Schlüßler). +- Making sure the current audio track is actually one of the ones available in a + recording (thanks to Sascha Volkenandt for reporting a problem when starting + replay of a recording that has no Dolby Digital audio after switching to a channel + that has DD and selecting the DD audio track). +- Removed 'flags' from tTrackId (thought we would need this, but apparently we don't). +- Making sure the "Mute" and "Volume+/-" keys don't interfere with digital audio. +- Fixed the "pre 1.3.19" compatibility mode for old Dolby Digital recordings (thanks + to Werner Fink for pointing out that this can be triggered in the default branch). +- Calling pesAssembler->Reset() in cDevice::AttachPlayer() to avoid problems with + residual data in replay and Transfer Mode (thanks to Werner Fink for pointing this + out). +- Added MPEG1 replay capability to cPesAssembler (thanks to Stefan Huelswitt). @@ -482,6 +482,9 @@ Version 1.2 The position of the channel info window in the OSD (either 'bottom' or 'top'). + Channel info time = 5 The time (in seconds) after which the channel info display + is removed if no key has been pressed. + Info on channel switch = yes Turns the display of the current/next information on or off when switching the channel. The information is diff --git a/PLUGINS.html b/PLUGINS.html index e8f456a..df6d0fa 100644 --- a/PLUGINS.html +++ b/PLUGINS.html @@ -14,18 +14,18 @@ Copyright © 2004 Klaus Schmidinger<br> <a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a> </center> <p> -<!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%> -Important modifications introduced in version 1.3.7 are marked like this. -<!--X1.3.7--></td></tr></table> -<!--X1.3.8--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%> +<!--X1.3.8--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%> Important modifications introduced in version 1.3.8 are marked like this. <!--X1.3.8--></td></tr></table> -<!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%> +<!--X1.3.18--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%> Important modifications introduced in version 1.3.18 are marked like this. <!--X1.3.18--></td></tr></table> -<!--X1.3.19--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%> +<!--X1.3.19--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%> Important modifications introduced in version 1.3.19 are marked like this. <!--X1.3.19--></td></tr></table> +<!--X1.3.20--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%> +Important modifications introduced in version 1.3.20 are marked like this. +<!--X1.3.20--></td></tr></table> <p> VDR provides an easy to use plugin interface that allows additional functionality to be added to the program by implementing a dynamically loadable library file. @@ -58,6 +58,9 @@ structures and allows it to hook itself into specific areas to perform special a <li><a href="#Command line arguments">Command line arguments</a> <li><a href="#Command line help">Command line help</a> <li><a href="#Getting started">Getting started</a> +<!--X1.3.20--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%> +<li><a href="#Shutting down">Shutting down</a> +<!--X1.3.20--></td></tr></table> <li><a href="#Main menu entry">Main menu entry</a> <li><a href="#User interaction">User interaction</a> <li><a href="#Housekeeping">Housekeeping</a> @@ -75,10 +78,8 @@ structures and allows it to hook itself into specific areas to perform special a <li><a href="#Receivers">Receivers</a> <li><a href="#Filters">Filters</a> <li><a href="#The On Screen Display">The On Screen Display</a> -<!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%> <li><a href="#Skins">Skins</a> <li><a href="#Themes">Themes</a> -<!--X1.3.7--></td></tr></table> <li><a href="#Devices">Devices</a> <li><a href="#Dolby Digital">Dolby Digital</a> <li><a href="#Remote Control">Remote Control</a> @@ -304,8 +305,11 @@ Constructing a plugin object shall not have any side effects or produce any outp since VDR, for instance, has to create the plugin objects in order to get their command line help - and after that immediately destroys them again. <p> -The <b>destructor</b> has to clean up any data created by the plugin, and has to -take care that any threads the plugin may have created will be stopped. +The <b>destructor</b> has to clean up any data created by the plugin. +<!--X1.3.20--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%> +Any threads the plugin may have created shall be stopped in the +<a href="#Shutting down"><tt>Stop()</tt></a> function. +<!--X1.3.20--></td></tr></table> <p> Of course, if your plugin doesn't define any member variables that need to be initialized (and deleted), you don't need to implement either of these functions. @@ -500,6 +504,25 @@ VDR to exit. If the plugin doesn't implement any background functionality or internationalized texts, it doesn't need to implement either of these functions. +<!--X1.3.20--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%> +<a name="Shutting down"><hr><h2>Shutting down</h2> + +<center><i><b>Stop it, right there!</b></i></center><p> + +If a plugin performs any background tasks, it shall implement the function + +<p><table><tr><td bgcolor=#F0F0F0><pre> +virtual void Stop(void); +</pre></td></tr></table><p> + +in which it shall stop them. +<p> +The <tt>Stop()</tt> function will only be called if a previous call to the +<a href="#Getting started"><tt>Start()</tt></a> function of that plugin has +returned <i>true</i>. The <tt>Stop()</tt> functions are called in the reverse order +as the <a href="#Getting started"><tt>Start()</tt></a> functions were called. +<!--X1.3.20--></td></tr></table> + <a name="Main menu entry"><hr><h2>Main menu entry</h2> <center><i><b>Today's special is...</b></i></center><p> @@ -1021,7 +1044,7 @@ public: Take a look at the files <tt>player.h</tt> and <tt>dvbplayer.c</tt> to see how VDR implements its own player for the VDR recordings. <p> -<!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%> +<!--X1.3.18--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%> To play the actual data, the player needs to call its member function <p><table><tr><td bgcolor=#F0F0F0><pre> @@ -1044,7 +1067,7 @@ bool DevicePoll(cPoller &Poller, int TimeoutMs = 0); to determine whether the device is ready for further data. <p> -<!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%> +<!--X1.3.18--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%> By default all audio track handling is done by the device a player is attached to. If the player can provide more than a single audio track, and has special @@ -1181,7 +1204,7 @@ public: }; cMyReceiver::cMyReceiver(int Pid) -<!--X1.3.19--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%> +<!--X1.3.19--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%> :cReceiver(0, -1, Pid) <!--X1.3.19--></td></tr></table> { @@ -1267,7 +1290,6 @@ and will automatically detach itself from the <tt>cDevice</tt>. <p> See VDR/eit.c or VDR/pat.c to learn how to process filter data. -<!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%> <a name="The On Screen Display"><hr><h2>The On Screen Display</h2> <center><i><b>Window to the world</b></i></center><p> @@ -1360,7 +1382,7 @@ public: virtual cSkinDisplayMenu *DisplayMenu(void); virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly); virtual cSkinDisplayVolume *DisplayVolume(void); -<!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%> +<!--X1.3.18--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%> virtual cSkinDisplayMessage *DisplayTrack(int NumTracks, const char * const *Tracks); <!--X1.3.18--></td></tr></table> virtual cSkinDisplayMessage *DisplayMessage(void); @@ -1382,7 +1404,7 @@ new cMySkin; in the <a href="#Getting started"><tt>Start()</tt></a> function of your plugin. Do not delete this object, it will be automatically deleted when the program ends. <p> -<!--X1.3.8--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%> +<!--X1.3.8--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%> In order to be able to easily identify plugins that implement a skin it is recommended that the name of such a plugin should be @@ -1441,7 +1463,6 @@ osd->DrawText(x, y, s, Theme.Color(clrButtonRedFg), Theme.Color(clrButtonRedB By default this will use the colors that have been defined in the respective <tt>THEME_CLR()</tt> line, but may be overwritten through user supplied theme files (see <tt>man vdr(5)</tt> for information about the format of a theme file). -<!--X1.3.7--></td></tr></table> <a name="Devices"><hr><h2>Devices</h2> @@ -1493,7 +1514,7 @@ repectively. If the device can provide more than a single audio track, it can implement the following function to make them available: -<!--X1.3.18--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%> +<!--X1.3.18--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%> <p><table><tr><td bgcolor=#F0F0F0><pre> virtual void SetAudioTrackDevice(eTrackType Type); virtual int GetAudioChannelDevice(void); @@ -1584,7 +1605,6 @@ handle section data. <p> <b>On Screen Display</b> <p> -<!--X1.3.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%> If your device provides On Screen Display (OSD) capabilities (which every device that is supposed to be used as a primary device should do), it shall implement an "OSD provider" class, derived from <tt>cOsdProvider</tt>, which, when its <tt>CreateOsd()</tt> @@ -1618,7 +1638,6 @@ in any way. All it needs to make sure is that the OSD will be visible to the user - whether this goes through OSD facilities of the physical device (like a "full featured" DVB card) or through a graphics adapter that overlays its output with the video signal, doesn't matter. -<!--X1.3.7--></td></tr></table> <p> <b>Initializing new devices</b> @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: channels.c 1.34 2005/01/16 13:49:30 kls Exp $ + * $Id: channels.c 1.35 2005/02/06 09:44:53 kls Exp $ */ #include "channels.h" @@ -640,7 +640,7 @@ cString cChannel::ToText(const cChannel *Channel) *q = 0; asprintf(&buffer, "%s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d\n", FullName, Channel->frequency, *Channel->ParametersToString(), *cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid); } - return buffer; + return cString(buffer, true); } cString cChannel::ToText(void) const diff --git a/channels.conf b/channels.conf index 67c319c..836e3be 100644 --- a/channels.conf +++ b/channels.conf @@ -26,7 +26,7 @@ NEUN LIVE Television,NEUN LIVE;BetaDigital:12480:vC34:S19.2E:27500:767:768=deu:3 DSF;BetaDigital:12480:vC34:S19.2E:27500:1023:1024=deu:0:0:900:133:33:0 HSE24,HSE24;BetaDigital:12480:vC34:S19.2E:27500:1279:1280=deu:37:0:40:133:33:0 Bloomberg TV Germany;Bloomberg:12551:vC56:S19.2E:22000:162:99=deu:0:0:12160:1:1108:0 -EURONEWS;CSAT:11817:vC34:S19.2E:27500:163:92=fra,93=eng,94=ita,95=esl,91=rus,98=por,99=deu:0:2:8004:1:1070:0 +EURONEWS;CSAT:11817:vC34:S19.2E:27500:163:92=fra,93=eng,94=ita,95=esl,91=rus,98=por,99=deu:0:0:8004:1:1070:0 rbb Brandenburg;ARD:12109:hC34:S19.2E:27500:601:602=deu:604:0:28205:1:1073:0 Sky News;BSkyB:11597:vC56:S19.2E:22000:305+131:306=eng:0:0:28707:1:1026:0 Veronica/FoxKids;CANAL+:12574:hC56:S19.2E:22000:518+8190:92=dut:38:622,602,100:5020:53:1109:0 @@ -48,10 +48,10 @@ PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:3 PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu,1793=deu;1795=deu:32:1722,1801,1702:11:133:2:0 PREMIERE 3,PREM 3;PREMIERE:11797:hC34:S19.2E:27500:2303:2304=deu,2305=deu:32:1722,1801,1702:43:133:2:0 PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu,769=deu:32:1801,1722,1702:9:133:2:0 -PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu:32:1801,1722,1702:29:133:2:0 +PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu,1281=deu:32:1801,1722,1702:29:133:2:0 PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1702,1801,1722:41:133:2:0 PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1722,1801,1702:20:133:2:0 -DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:0:1722,1801,1702:34:133:17:0 +DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:0:1801,1722,1702:34:133:17:0 :Premiere Direkt PREMIERE DIREKT,DIREKT;PREMIERE:12031:hC34:S19.2E:27500:2815:2816=deu,2817=deu;2819=deu:0:0:18:133:4:0 :PW Erotic @@ -113,7 +113,7 @@ Animal Plnt+;BSkyB:12070:hC23:S28.2E:27500:2314+2307:2315=eng:0:960,961:50002:2: S1T;BSkyB:12285:vC23:S28.2E:27500:2311+2304:2312=eng,2313=NAR:2307:960,961:4409:2:2030:0 CNN;BSkyB:12051:vC23:S28.2E:27500:2313:2315=eng:2314:0:7140:2:2018:0 BBC PARL'MNT:12129:vC23:S28.2E:27500:2304:2306=eng,2307=eng:2305:0:7300:2:2022:0 -ADRIATICOSAT;T-Systems/MTI:11200:vC56:S13.0E:27500:413:414=ita:0:0:4733:318:13400:0 +JOLLY FILM;T-Systems/MTI:11200:vC56:S13.0E:27500:413:414=ita:0:0:4733:318:13400:0 Euro1080;EURO1080:12168:vC34:S19.2E:27500:308:256:0:FF:21100:1:1088:0 Astra HD:12441:vC34:S19.2E:27500:133+80:134=eng:0:FF:29700:0:0:0 eng-WRN-multi;WRN:12597:vC34:S13.0E:27500:0:2132:0:0:8230:318:9400:0 @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.c 1.131 2005/01/09 12:14:58 kls Exp $ + * $Id: config.c 1.132 2005/02/05 10:43:04 kls Exp $ */ #include "config.h" @@ -283,6 +283,7 @@ cSetup::cSetup(void) UpdateChannels = 4; UseDolbyDigital = 1; ChannelInfoPos = 0; + ChannelInfoTime = 5; OSDLeft = 54; OSDTop = 45; OSDWidth = 624; @@ -438,6 +439,7 @@ bool cSetup::Parse(const char *Name, const char *Value) else if (!strcasecmp(Name, "UpdateChannels")) UpdateChannels = atoi(Value); else if (!strcasecmp(Name, "UseDolbyDigital")) UseDolbyDigital = atoi(Value); else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value); + else if (!strcasecmp(Name, "ChannelInfoTime")) ChannelInfoTime = atoi(Value); else if (!strcasecmp(Name, "OSDLeft")) OSDLeft = atoi(Value); else if (!strcasecmp(Name, "OSDTop")) OSDTop = atoi(Value); else if (!strcasecmp(Name, "OSDWidth")) { OSDWidth = atoi(Value); if (OSDWidth < 100) OSDWidth *= 12; OSDWidth &= ~0x07; } // OSD width must be a multiple of 8 @@ -500,6 +502,7 @@ bool cSetup::Save(void) Store("UpdateChannels", UpdateChannels); Store("UseDolbyDigital", UseDolbyDigital); Store("ChannelInfoPos", ChannelInfoPos); + Store("ChannelInfoTime", ChannelInfoTime); Store("OSDLeft", OSDLeft); Store("OSDTop", OSDTop); Store("OSDWidth", OSDWidth); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 1.210 2005/01/09 16:50:11 kls Exp $ + * $Id: config.h 1.212 2005/02/05 10:43:22 kls Exp $ */ #ifndef __CONFIG_H @@ -20,8 +20,8 @@ #include "i18n.h" #include "tools.h" -#define VDRVERSION "1.3.19" -#define VDRVERSNUM 10319 // Version * 10000 + Major * 100 + Minor +#define VDRVERSION "1.3.20" +#define VDRVERSNUM 10320 // Version * 10000 + Major * 100 + Minor #define MAXPRIORITY 99 #define MAXLIFETIME 99 @@ -241,6 +241,7 @@ public: int UpdateChannels; int UseDolbyDigital; int ChannelInfoPos; + int ChannelInfoTime; int OSDLeft, OSDTop, OSDWidth, OSDHeight; int OSDMessageTime; int UseSmallFont; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 1.78 2005/01/23 15:41:05 kls Exp $ + * $Id: device.c 1.87 2005/02/06 14:10:37 kls Exp $ */ #include "device.h" @@ -31,7 +31,8 @@ private: public: cPesAssembler(void); ~cPesAssembler(); - int ExpectedLength(void) { return data[4] * 256 + data[5] + 6; } + int ExpectedLength(void) { return PacketSize(data); } + static int PacketSize(const uchar *data); int Length(void) { return length; } const uchar *Data(void) { return data; } void Reset(void); @@ -100,6 +101,38 @@ void cPesAssembler::Put(const uchar *Data, int Length) } } +int cPesAssembler::PacketSize(const uchar *data) +{ + // we need atleast 6 bytes of data here !!! + switch (data[3]) { + default: + case 0x00 ... 0xB8: // video stream start codes + case 0xB9: // Program end + case 0xBC: // Programm stream map + case 0xF0 ... 0xFF: // reserved + return 6; + + case 0xBA: // Pack header + if ((data[4] & 0xC0) == 0x40) // MPEG2 + return 14; + // to be absolutely correct we would have to add the stuffing bytes + // as well, but at this point we only may have 6 bytes of data avail- + // able. So it's up to the higher level to resync... + //return 14 + (data[13] & 0x07); // add stuffing bytes + else // MPEG1 + return 12; + + case 0xBB: // System header + case 0xBD: // Private stream1 + case 0xBE: // Padding stream + case 0xBF: // Private stream2 (navigation data) + case 0xC0 ... 0xCF: // all the rest (the real packets) + case 0xD0 ... 0xDF: + case 0xE0 ... 0xEF: + return 6 + data[4] * 256 + data[5]; + } +} + // --- cDevice --------------------------------------------------------------- // The default priority for non-primary devices: @@ -137,6 +170,7 @@ cDevice::cDevice(void) pesAssembler = new cPesAssembler; ClrAvailableTracks(); currentAudioTrack = ttAudioFirst; + currentAudioTrackMissingCount = 0; for (int i = 0; i < MAXRECEIVERS; i++) receiver[i] = NULL; @@ -281,11 +315,11 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDe void cDevice::Shutdown(void) { + primaryDevice = NULL; for (int i = 0; i < numDevices; i++) { delete device[i]; device[i] = NULL; } - primaryDevice = NULL; } bool cDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY) @@ -551,26 +585,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) for (int i = 0; i < MAXDPIDS; i++) SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i)); } - // Select the preferred audio track: - eTrackType PreferredTrack = ttAudioFirst; - int LanguagePreference = -1; - int StartCheck = Setup.CurrentDolby ? ttDolbyFirst : ttAudioFirst; - int EndCheck = ttDolbyLast; - for (int i = StartCheck; i <= EndCheck; i++) { - const tTrackId *TrackId = GetTrack(eTrackType(i)); - if (TrackId && TrackId->id && I18nIsPreferredLanguage(Setup.AudioLanguages, I18nLanguageIndex(TrackId->language), LanguagePreference)) - PreferredTrack = eTrackType(i); - if (Setup.CurrentDolby && i == ttDolbyLast) { - i = ttAudioFirst - 1; - EndCheck = ttAudioLast; - } - } - // Make sure we're set to an available audio track: - const tTrackId *Track = GetTrack(GetCurrentAudioTrack()); - if (!Track || !Track->id || PreferredTrack != GetCurrentAudioTrack()) - SetCurrentAudioTrack(PreferredTrack); - // Fall back to stereo: - SetAudioChannel(0); + EnsureAudioTrack(true); } cStatus::MsgChannelSwitch(this, Channel->Number()); // only report status if channel switch successfull } @@ -663,10 +678,12 @@ void cDevice::ClrAvailableTracks(bool DescriptionsOnly) else { memset(availableTracks, 0, sizeof(availableTracks)); pre_1_3_19_PrivateStream = false; + SetAudioChannel(0); // fall back to stereo + currentAudioTrackMissingCount = 0; } } -bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description, uint32_t Flags) +bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description) { eTrackType t = eTrackType(Type + Index); if (Type == ttAudio && IS_AUDIO_TRACK(t) || @@ -675,10 +692,12 @@ bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const c strn0cpy(availableTracks[t].language, Language, sizeof(availableTracks[t].language)); if (Description) strn0cpy(availableTracks[t].description, Description, sizeof(availableTracks[t].description)); - if (Id) { - availableTracks[t].flags = Flags; + if (Id) availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking - } + if (t == currentAudioTrack) + currentAudioTrackMissingCount = 0; + else if (!availableTracks[currentAudioTrack].id && currentAudioTrackMissingCount++ > NumAudioTracks() * 10) + EnsureAudioTrack(); return true; } else @@ -718,6 +737,31 @@ bool cDevice::SetCurrentAudioTrack(eTrackType Type) return false; } +void cDevice::EnsureAudioTrack(bool Force) +{ + if (Force || !availableTracks[currentAudioTrack].id) { + eTrackType PreferredTrack = ttAudioFirst; + int LanguagePreference = -1; + int StartCheck = Setup.CurrentDolby ? ttDolbyFirst : ttAudioFirst; + int EndCheck = ttDolbyLast; + for (int i = StartCheck; i <= EndCheck; i++) { + const tTrackId *TrackId = GetTrack(eTrackType(i)); + if (TrackId && TrackId->id && I18nIsPreferredLanguage(Setup.AudioLanguages, I18nLanguageIndex(TrackId->language), LanguagePreference)) + PreferredTrack = eTrackType(i); + if (Setup.CurrentDolby && i == ttDolbyLast) { + i = ttAudioFirst - 1; + EndCheck = ttAudioLast; + } + } + // Make sure we're set to an available audio track: + const tTrackId *Track = GetTrack(GetCurrentAudioTrack()); + if (Force || !Track || !Track->id || PreferredTrack != GetCurrentAudioTrack()) { + dsyslog("setting audio track to %d", PreferredTrack); + SetCurrentAudioTrack(PreferredTrack); + } + } +} + bool cDevice::CanReplay(void) const { return HasDecoder(); @@ -772,6 +816,7 @@ bool cDevice::AttachPlayer(cPlayer *Player) if (player) Detach(player); ClrAvailableTracks(); + pesAssembler->Reset(); player = Player; SetPlayMode(player->playMode); player->device = this; @@ -831,6 +876,7 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) int d = End - Start; int w = d; switch (c) { + case 0xBE: // padding stream, needed for MPEG1 case 0xE0 ... 0xEF: // video w = PlayVideo(Start, d); break; @@ -842,13 +888,10 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) case 0xBD: { // private stream 1 int PayloadOffset = Data[8] + 9; uchar SubStreamId = Data[PayloadOffset]; - uchar SubStreamType = SubStreamId & 0xE0; + uchar SubStreamType = SubStreamId & 0xF0; uchar SubStreamIndex = SubStreamId & 0x1F; // Compatibility mode for old VDR recordings, where 0xBD was only AC3: - //TODO apparently this doesn't work for old ORF Dolby Digital recordings - if (!pre_1_3_19_PrivateStream && (Data[6] & 4) && Data[PayloadOffset] == 0x0B && Data[PayloadOffset + 1] == 0x77) - pre_1_3_19_PrivateStream = true; if (pre_1_3_19_PrivateStream) { SubStreamId = c; SubStreamType = 0x80; @@ -857,6 +900,7 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) switch (SubStreamType) { case 0x20: // SPU + case 0x30: // SPU break; case 0x80: // AC3 & DTS if (Setup.UseDolbyDigital) { @@ -873,6 +917,13 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) if (!VideoOnly && SubStreamId == availableTracks[currentAudioTrack].id) w = PlayAudio(Start, d); break; + default: + // Compatibility mode for old VDR recordings, where 0xBD was only AC3: + if (!pre_1_3_19_PrivateStream) { + dsyslog("switching to pre 1.3.19 Dolby Digital compatibility mode"); + ClrAvailableTracks(); + pre_1_3_19_PrivateStream = true; + } } } break; @@ -924,7 +975,7 @@ int cDevice::PlayPes(const uchar *Data, int Length, bool VideoOnly) int i = 0; while (i <= Length - 6) { if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) { - int l = Data[i + 4] * 256 + Data[i + 5] + 6; + int l = cPesAssembler::PacketSize(&Data[i]); if (i + l > Length) { // Store incomplete PES packet for later completion: pesAssembler->Put(Data + i, Length - i); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 1.53 2005/01/22 14:58:07 kls Exp $ + * $Id: device.h 1.55 2005/02/06 11:43:04 kls Exp $ */ #ifndef __DEVICE_H @@ -78,8 +78,6 @@ struct tTrackId { uint16_t id; // The PES packet id or the PID. char language[8]; // something like either "eng" or "deu/eng" char description[32]; // something like "Dolby Digital 5.1" - // for future use: - uint32_t flags; // Used to further identify the actual track. }; class cChannel; @@ -315,17 +313,18 @@ public: private: tTrackId availableTracks[ttMaxTrackTypes]; eTrackType currentAudioTrack; + int currentAudioTrackMissingCount; bool pre_1_3_19_PrivateStream; protected: virtual void SetAudioTrackDevice(eTrackType Type); ///< Sets the current audio track to the given value. public: void ClrAvailableTracks(bool DescriptionsOnly = false); - bool SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language = NULL, const char *Description = NULL, uint32_t Flags = 0); + bool SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language = NULL, const char *Description = NULL); ///< Sets the track of the given Type and Index to the given values. ///< Type must be one of the basic eTrackType values, like ttAudio or ttDolby. ///< Index tells which track of the given basic type is meant. - ///< If Id is 0 any existing id (and flags) will be left untouched and only the + ///< If Id is 0 any existing id will be left untouched and only the ///< given Language and Description will be set. ///< \return Returns true if the track was set correctly, false otherwise. const tTrackId *GetTrack(eTrackType Type); @@ -339,6 +338,10 @@ public: bool SetCurrentAudioTrack(eTrackType Type); ///< Sets the current audio track to the given Type. ///< \return Returns true if Type is a valid audio track, false otherwise. + void EnsureAudioTrack(bool Force = false); + ///< Makes sure an audio track is selected that is actually available. + ///< If Force is true, the language and Dolby Digital settings will + ///< be verified even if the current audio track is available. // Audio facilities diff --git a/dvbdevice.c b/dvbdevice.c index e8862cb..269c0a2 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.116 2005/01/16 12:05:13 kls Exp $ + * $Id: dvbdevice.c 1.117 2005/02/06 12:30:14 kls Exp $ */ #include "dvbdevice.h" @@ -842,6 +842,8 @@ void cDvbDevice::SetAudioChannelDevice(int AudioChannel) void cDvbDevice::SetVolumeDevice(int Volume) { if (HasDecoder()) { + if (digitalAudio) + Volume = 0; audio_mixer_t am; // conversion for linear volume response: am.volume_left = am.volume_right = 2 * Volume - Volume * Volume / 255; @@ -854,8 +856,8 @@ void cDvbDevice::SetDigitalAudioDevice(bool On) if (digitalAudio != On) { if (digitalAudio) cCondWait::SleepMs(1000); // Wait until any leftover digital data has been flushed - SetVolumeDevice(On || IsMute() ? 0 : CurrentVolume()); digitalAudio = On; + SetVolumeDevice(On || IsMute() ? 0 : CurrentVolume()); } } @@ -8,7 +8,7 @@ * * parts of this file are derived from the OMS program. * - * $Id: dvbspu.c 1.11 2005/01/08 09:57:03 kls Exp $ + * $Id: dvbspu.c 1.12 2005/02/06 09:54:51 kls Exp $ */ #include <assert.h> @@ -216,6 +216,7 @@ void cDvbSpuBitmap::putFieldData(int field, uint8_t * data, uint8_t * endp) #define CMD_SPU_SET_ALPHA 0x04 #define CMD_SPU_SET_SIZE 0x05 #define CMD_SPU_SET_PXD_OFFSET 0x06 +#define CMD_SPU_CHG_COLCON 0x07 #define CMD_SPU_EOF 0xff #define spuU32(i) ((spu[i] << 8) + spu[i+1]) @@ -509,6 +510,12 @@ int cDvbSpuDecoder::setTime(uint32_t pts) i += 5; break; + case CMD_SPU_CHG_COLCON: { + int size = spuU32(i + 1); + i += 1 + size; + } + break; + case CMD_SPU_MENU: DEBUG("\tspu menu\n"); state = spMENU; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: i18n.c 1.172 2005/01/22 10:38:44 kls Exp $ + * $Id: i18n.c 1.175 2005/02/05 10:46:30 kls Exp $ * * Translations provided by: * @@ -952,7 +952,7 @@ const tI18nPhrase Phrases[] = { "Scansione", "",//TODO "",//TODO - "",//TODO + "Scan", "",//TODO "Päivitä", "",//TODO @@ -1668,7 +1668,7 @@ const tI18nPhrase Phrases[] = { "Hierarchy", "Hierarchy", "Hierarchy", - "Hierarchie", + "Hiérarchie", "Hierarchy", "Hierarkia", "Hierachia", @@ -1795,7 +1795,7 @@ const tI18nPhrase Phrases[] = { "VPS", "",// TODO "",// TODO - "",// TODO + "VPS", "",// TODO "VPS", "",// TODO @@ -2306,7 +2306,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "",//TODO - "",//TODO + "Pas d'audio disponible!", "",//TODO "",//TODO "",//TODO @@ -2575,7 +2575,7 @@ const tI18nPhrase Phrases[] = { "Superficie Skin", "",// TODO "",// TODO - "",// TODO + "Skin", "",// TODO "Ulkoasu", "",// TODO @@ -2596,7 +2596,7 @@ const tI18nPhrase Phrases[] = { "Tema", "",// TODO "",// TODO - "",// TODO + "Thème", "",// TODO "Teema", "",// TODO @@ -2617,7 +2617,7 @@ const tI18nPhrase Phrases[] = { "Sinistra", "",// TODO "",// TODO - "",// TODO + "Gauche", "",// TODO "Vaakakeskitys", "",// TODO @@ -2638,7 +2638,7 @@ const tI18nPhrase Phrases[] = { "Cima", "",// TODO "",// TODO - "",// TODO + "Haut", "",// TODO "Pystykeskitys", "",// TODO @@ -2701,7 +2701,7 @@ const tI18nPhrase Phrases[] = { "Tempo del messaggio (s)", "Weergave duur van berichten (s)", "Mostrar contador (s)", - "Durée affichage écran (s)", + "Durée affichage message (s)", "Tid meldinger skal vises (s)", "Viestien esitysaika (s)", "Czas wyswietlania wiadomosci (s)", @@ -2722,7 +2722,7 @@ const tI18nPhrase Phrases[] = { "Utilizzare caratteri piccoli", "",// TODO "",// TODO - "",// TODO + "Utiliser les petits caractères", "",// TODO "Käytä pieniä kirjasimia", "",// TODO @@ -2743,7 +2743,7 @@ const tI18nPhrase Phrases[] = { "mai", "",// TODO "",// TODO - "",// TODO + "jamais", "",// TODO "ei koskaan", "",// TODO @@ -2764,7 +2764,7 @@ const tI18nPhrase Phrases[] = { "in base alla superficie", "",// TODO "",// TODO - "",// TODO + "Dépend du skin", "",// TODO "ulkoasun mukaan", "",// TODO @@ -2785,7 +2785,7 @@ const tI18nPhrase Phrases[] = { "sempre", "",// TODO "",// TODO - "",// TODO + "toujours", "",// TODO "aina", "",// TODO @@ -2821,6 +2821,27 @@ const tI18nPhrase Phrases[] = { "Kanaliinfo asukoht", "Placering af kanalinfo", }, + { "Setup.OSD$Channel info time (s)", + "Anzeigedauer für Kanal-Info (s)", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "Durée affichage infos chaînes (s)", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + }, { "Setup.OSD$Info on channel switch", "Info beim Kanalwechsel", "Pokazi naziv kanala", @@ -2953,7 +2974,7 @@ const tI18nPhrase Phrases[] = { "Visualizzazione dati vecchi (min)", "",// TODO "",// TODO - "",// TODO + "Montrer l'EPG plus vieux de m min", "",// TODO "Vanha tieto näkyy (min)", "",// TODO @@ -3016,7 +3037,7 @@ const tI18nPhrase Phrases[] = { "Lingue preferite", "",// TODO "",// TODO - "",// TODO + "Langues préférées", "",// TODO "Suosikkikielet", "",// TODO @@ -3037,7 +3058,7 @@ const tI18nPhrase Phrases[] = { "Lingua preferita", "",// TODO "",// TODO - "",// TODO + "Langue préférée", "",// TODO "Suosikkikieli", "",// TODO @@ -3106,7 +3127,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "",//TODO - "",//TODO + "Utiliser le Dolby Digital", "",//TODO "",//TODO "",//TODO @@ -3121,7 +3142,7 @@ const tI18nPhrase Phrases[] = { "Aggiornare i canali", "",// TODO "",// TODO - "",// TODO + "Mettre à jour les chaînes", "",// TODO "Päivitä kanavat", "",// TODO @@ -3142,7 +3163,7 @@ const tI18nPhrase Phrases[] = { "solo nomi", "",// TODO "",// TODO - "",// TODO + "Seulement les noms", "",// TODO "vain nimet", "",// TODO @@ -3163,7 +3184,7 @@ const tI18nPhrase Phrases[] = { "nomi e PIDs", "",// TODO "",// TODO - "",// TODO + "Noms et PIDs", "",// TODO "nimet ja PID:it", "",// TODO @@ -3184,7 +3205,7 @@ const tI18nPhrase Phrases[] = { "aggiungere canali nuovi", "",// TODO "",// TODO - "",// TODO + "Ajouter les nouvelles chaînes", "",// TODO "lisää uudet kanavat", "",// TODO @@ -3205,7 +3226,7 @@ const tI18nPhrase Phrases[] = { "aggiungere transponder nuovi", "",// TODO "",// TODO - "",// TODO + "Ajouter les nouveaux transpondeurs", "",// TODO "lisää uudet transponderit", "",// TODO @@ -3239,7 +3260,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "",//TODO - "",//TODO + "Audio sprog (ant.)", }, { "Setup.DVB$Audio language", // note the singular "",//TODO @@ -3260,7 +3281,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "",//TODO - "",//TODO + "Audio sprog", }, { "Setup.LNB$SLOF (MHz)", "SLOF (MHz)", @@ -3541,7 +3562,7 @@ const tI18nPhrase Phrases[] = { "Utilizzare VPS", "",// TODO "",// TODO - "",// TODO + "Utiliser le VPS", "",// TODO "Käytä VPS-toimintoa", "",// TODO @@ -3562,7 +3583,7 @@ const tI18nPhrase Phrases[] = { "Margine VPS", "",// TODO "",// TODO - "",// TODO + "Marge VPS", "",// TODO "VPS-toiminnon aloitusmarginaali (s)", "",// TODO @@ -3814,7 +3835,7 @@ const tI18nPhrase Phrases[] = { "Timeout Zapping", "Zap timeout (s)", "",// TODO - "",// TODO + "Prise en compte dernière chaîne (s)", "",// TODO "Kanavavalinnan odotusaika (s)", "",// TODO @@ -4685,7 +4706,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO + "Audio", "",// TODO "",// TODO "",// TODO @@ -4743,7 +4764,7 @@ const tI18nPhrase Phrases[] = { "off", "uit", "off", - "",// TODO + "off", "",// TODO "pois", "wyl.", @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.337 2005/01/15 16:32:34 kls Exp $ + * $Id: menu.c 1.340 2005/02/06 11:33:13 kls Exp $ */ #include "menu.h" @@ -1769,6 +1769,7 @@ void cMenuSetupOSD::Set(void) Add(new cMenuEditIntItem( tr("Setup.OSD$Message time (s)"), &data.OSDMessageTime, 1, 60)); Add(new cMenuEditStraItem(tr("Setup.OSD$Use small font"), &data.UseSmallFont, 3, useSmallFontTexts)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Channel info position"), &data.ChannelInfoPos, tr("bottom"), tr("top"))); + Add(new cMenuEditIntItem( tr("Setup.OSD$Channel info time (s)"), &data.ChannelInfoTime, 1, 60)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Info on channel switch"), &data.ShowInfoOnChSwitch)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Scroll pages"), &data.MenuScrollPage)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Sort timers"), &data.SortTimers)); @@ -2513,10 +2514,8 @@ eOSState cMenuMain::ProcessKey(eKeys Key) state = replaying ? osContinue : osRecord; break; case kGreen: if (!HadSubMenu) { - if (cDevice::PrimaryDevice()->NumAudioTracks() > 1) { - cRemote::Put(kAudio, true); - state = osEnd; - } + cRemote::Put(kAudio, true); + state = osEnd; } break; case kYellow: if (!HadSubMenu) @@ -2578,7 +2577,6 @@ static void SetTrackDescriptions(void) // --- cDisplayChannel ------------------------------------------------------- #define DIRECTCHANNELTIMEOUT 1000 //ms -#define INFOTIMEOUT 5000 //ms cDisplayChannel::cDisplayChannel(int Number, bool Switched) :cOsdObject(true) @@ -2766,7 +2764,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key) return osEnd; } }; - if (lastTime.Elapsed() < INFOTIMEOUT) { + if (lastTime.Elapsed() < (uint64)(Setup.ChannelInfoTime * 1000)) { if (!number && group < 0 && channel && channel->Number() != cDevice::CurrentChannel()) Refresh(); // makes sure a channel switch through the SVDRP CHAN command is displayed DisplayInfo(); @@ -2852,6 +2850,7 @@ cDisplayTracks *cDisplayTracks::currentDisplayTracks = NULL; cDisplayTracks::cDisplayTracks(void) :cOsdObject(true) { + cDevice::PrimaryDevice()->EnsureAudioTrack(); // Get the actual audio track descriptions from the EPG if we're not replaying: if (!cDevice::PrimaryDevice()->Replaying() || cTransferControl::ReceiverDevice()) SetTrackDescriptions(); @@ -12,7 +12,7 @@ # See the main source file 'vdr.c' for copyright information and # how to reach the author. # -# $Id: newplugin 1.17 2004/10/16 12:12:43 kls Exp $ +# $Id: newplugin 1.18 2005/01/30 13:50:05 kls Exp $ $PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n"; @@ -164,6 +164,7 @@ public: virtual bool ProcessArgs(int argc, char *argv[]); virtual bool Initialize(void); virtual bool Start(void); + virtual void Stop(void); virtual void Housekeeping(void); virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; } virtual cOsdObject *MainMenuAction(void); @@ -207,6 +208,11 @@ bool cPlugin${PLUGIN_CLASS}::Start(void) return true; } +void cPlugin${PLUGIN_CLASS}::Stop(void) +{ + // Stop any background activities the plugin shall perform. +} + void cPlugin${PLUGIN_CLASS}::Housekeeping(void) { // Perform any cleanup or other regular tasks. @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.c 1.11 2005/01/16 13:54:34 kls Exp $ + * $Id: pat.c 1.12 2005/01/25 21:02:11 kls Exp $ */ #include "pat.h" @@ -324,10 +324,10 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length SI::PMT::Stream stream; int Vpid = 0; int Ppid = pmt.getPCRPid(); - int Apids[MAXAPIDS] = { 0 }; - int Dpids[MAXDPIDS] = { 0 }; - char ALangs[MAXAPIDS][4] = { "" }; - char DLangs[MAXDPIDS][4] = { "" }; + int Apids[MAXAPIDS + 1] = { 0 }; + int Dpids[MAXDPIDS + 1] = { 0 }; + char ALangs[MAXAPIDS + 1][4] = { "" }; + char DLangs[MAXDPIDS + 1][4] = { "" }; int Tpid = 0; int NumApids = 0; int NumDpids = 0; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: player.h 1.14 2004/12/30 10:44:34 kls Exp $ + * $Id: player.h 1.15 2005/02/06 11:44:56 kls Exp $ */ #ifndef __PLAYER_H @@ -19,7 +19,7 @@ private: cDevice *device; ePlayMode playMode; protected: - bool DeviceSetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language = NULL, const char *Description = NULL, uint32_t Flags = 0) { return device ? device->SetAvailableTrack(Type, Index, Id, Language, Description, Flags) : false; } + bool DeviceSetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language = NULL, const char *Description = NULL) { return device ? device->SetAvailableTrack(Type, Index, Id, Language, Description) : false; } bool DevicePoll(cPoller &Poller, int TimeoutMs = 0) { return device ? device->Poll(Poller, TimeoutMs) : false; } bool DeviceFlush(int TimeoutMs = 0) { return device ? device->Flush(TimeoutMs) : true; } void DeviceTrickSpeed(int Speed) { if (device) device->TrickSpeed(Speed); } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: plugin.c 1.12 2004/12/19 12:05:28 kls Exp $ + * $Id: plugin.c 1.13 2005/01/30 14:05:20 kls Exp $ */ #include "plugin.h" @@ -28,6 +28,7 @@ char *cPlugin::configDirectory = NULL; cPlugin::cPlugin(void) { name = NULL; + started = false; } cPlugin::~cPlugin() @@ -60,6 +61,10 @@ bool cPlugin::Start(void) return true; } +void cPlugin::Stop(void) +{ +} + void cPlugin::Housekeeping(void) { } @@ -322,6 +327,7 @@ bool cPluginManager::StartPlugins(void) Setup.OSDLanguage = Language; if (!p->Start()) return false; + p->started = true; } } return true; @@ -366,15 +372,25 @@ cPlugin *cPluginManager::GetPlugin(const char *Name) return NULL; } -void cPluginManager::Shutdown(bool Log) +void cPluginManager::StopPlugins(void) +{ + for (cDll *dll = dlls.Last(); dll; dll = dlls.Prev(dll)) { + cPlugin *p = dll->Plugin(); + if (p && p->started) { + isyslog("stopping plugin: %s", p->Name()); + p->Stop(); + p->started = false; + } + } +} + +void cPluginManager::Shutdown(void) { cDll *dll; while ((dll = dlls.Last()) != NULL) { - if (Log) { - cPlugin *p = dll->Plugin(); - if (p) - isyslog("stopping plugin: %s", p->Name()); - } + cPlugin *p = dll->Plugin(); + if (p) + isyslog("deleting plugin: %s", p->Name()); dlls.Del(dll); } } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: plugin.h 1.7 2004/04/30 13:46:21 kls Exp $ + * $Id: plugin.h 1.8 2005/01/30 14:03:48 kls Exp $ */ #ifndef __PLUGIN_H @@ -19,9 +19,11 @@ class cPlugin { friend class cDll; + friend class cPluginManager; private: static char *configDirectory; const char *name; + bool started; void SetName(const char *s); public: cPlugin(void); @@ -35,6 +37,7 @@ public: virtual bool ProcessArgs(int argc, char *argv[]); virtual bool Initialize(void); virtual bool Start(void); + virtual void Stop(void); virtual void Housekeeping(void); virtual const char *MainMenuEntry(void); @@ -85,7 +88,8 @@ public: static bool HasPlugins(void); static cPlugin *GetPlugin(int Index); static cPlugin *GetPlugin(const char *Name); - void Shutdown(bool Log = false); + void StopPlugins(void); + void Shutdown(void); }; #endif //__PLUGIN_H diff --git a/recording.c b/recording.c index 7ba93b3..c6460f2 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 1.94 2004/12/26 11:55:24 kls Exp $ + * $Id: recording.c 1.95 2005/02/06 09:46:31 kls Exp $ */ #include "recording.h" @@ -719,7 +719,7 @@ cString cMark::ToText(void) { char *buffer; asprintf(&buffer, "%s%s%s\n", *IndexToHMSF(position, true), comment ? " " : "", comment ? comment : ""); - return buffer; + return cString(buffer, true); } bool cMark::Parse(const char *s) @@ -11,7 +11,7 @@ * The cDolbyRepacker code was originally written by Reinhard Nissl <rnissl@gmx.de>, * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. * - * $Id: remux.c 1.27 2005/01/23 12:56:39 kls Exp $ + * $Id: remux.c 1.28 2005/02/05 11:56:42 kls Exp $ */ #include "remux.h" @@ -24,12 +24,14 @@ class cRepacker { protected: + int maxPacketSize; uint8_t subStreamId; public: - cRepacker(void) { subStreamId = 0; } + cRepacker(void) { maxPacketSize = 6 + 65535; subStreamId = 0; } virtual ~cRepacker() {} virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) = 0; virtual int BreakAt(const uchar *Data, int Count) = 0; + void SetMaxPacketSize(int MaxPacketSize) { maxPacketSize = MaxPacketSize; } void SetSubStreamId(uint8_t SubStreamId) { subStreamId = SubStreamId; } }; @@ -40,6 +42,7 @@ private: static int frameSizes[]; uchar fragmentData[6 + 65535]; int fragmentLen; + int fragmentTodo; uchar pesHeader[6 + 3 + 255 + 4 + 4]; int pesHeaderLen; uchar chk1; @@ -50,15 +53,21 @@ private: find_77, store_chk1, store_chk2, - get_length + get_length, + output_packet } state; void Reset(void); + void ResetPesHeader(void); + void AppendSubStreamID(void); + bool FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite); + bool StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite); public: cDolbyRepacker(void); virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count); virtual int BreakAt(const uchar *Data, int Count); }; +// frameSizes are in words, i. e. multiply them by 2 to get bytes int cDolbyRepacker::frameSizes[] = { // fs = 48 kHz 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192, 224, 224, @@ -93,78 +102,152 @@ cDolbyRepacker::cDolbyRepacker(void) Reset(); } -void cDolbyRepacker::Reset() +void cDolbyRepacker::AppendSubStreamID(void) +{ + if (subStreamId) { + pesHeader[pesHeaderLen++] = subStreamId; + pesHeader[pesHeaderLen++] = 0x00; + pesHeader[pesHeaderLen++] = 0x00; + pesHeader[pesHeaderLen++] = 0x00; + } +} + +void cDolbyRepacker::ResetPesHeader(void) { - state = find_0b; pesHeader[6] = 0x80; pesHeader[7] = 0x00; pesHeader[8] = 0x00; pesHeaderLen = 9; + AppendSubStreamID(); +} + +void cDolbyRepacker::Reset(void) +{ + ResetPesHeader(); + state = find_0b; ac3todo = 0; chk1 = 0; chk2 = 0; fragmentLen = 0; + fragmentTodo = 0; } -int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) +bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite) { - // check for MPEG 2 - if ((Data[6] & 0xC0) != 0x80) - return 0; - // copy header information for later use - if (Data[6] != 0x80 || Data[7] != 0x00 || Data[8] != 0x00) { - pesHeaderLen = Data[8] + 6 + 3; - memcpy(pesHeader, Data, pesHeaderLen); - } - - const uchar *data = Data + pesHeaderLen; - int done = pesHeaderLen; - int todo = Count - done; - - // finish remainder of ac3 frame - if (ac3todo > 0) { - int bite; - // enough data available to put PES packet into buffer? - if (ac3todo <= todo) { - // output a previous fragment first - if (fragmentLen > 0) { - bite = fragmentLen; - int n = ResultBuffer->Put(fragmentData, bite); - if (bite != n) { - Reset(); - return done; - } - fragmentLen = 0; - } - bite = ac3todo; - int n = ResultBuffer->Put(data, bite); - if (bite != n) { + // enough data available to put PES packet into buffer? + if (fragmentTodo <= Todo) { + // output a previous fragment first + if (fragmentLen > 0) { + Bite = fragmentLen; + int n = ResultBuffer->Put(fragmentData, Bite); + if (Bite != n) { Reset(); - return done + n; + return false; } + fragmentLen = 0; } - else { - // copy the fragment into separate buffer for later processing - bite = todo; - if (fragmentLen + bite > (int)sizeof(fragmentData)) { - Reset(); - return done; - } - memcpy(fragmentData + fragmentLen, data, bite); - fragmentLen += bite; + Bite = fragmentTodo; + int n = ResultBuffer->Put(Data, Bite); + if (Bite != n) { + Reset(); + Done += n; + return false; + } + fragmentTodo = 0; + // ac3 frame completely processed? + if (Bite >= ac3todo) + state = find_0b; // go on with finding start of next packet + } + else { + // copy the fragment into separate buffer for later processing + Bite = Todo; + if (fragmentLen + Bite > (int)sizeof(fragmentData)) { + Reset(); + return false; + } + memcpy(fragmentData + fragmentLen, Data, Bite); + fragmentLen += Bite; + fragmentTodo -= Bite; + } + return true; +} + +bool cDolbyRepacker::StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite) +{ + int packetLen = pesHeaderLen + ac3todo; + // limit packet to maximum size + if (packetLen > maxPacketSize) + packetLen = maxPacketSize; + pesHeader[4] = (packetLen - 6) >> 8; + pesHeader[5] = (packetLen - 6) & 0xFF; + Bite = pesHeaderLen; + // enough data available to put PES packet into buffer? + if (packetLen - pesHeaderLen <= Todo) { + int n = ResultBuffer->Put(pesHeader, Bite); + if (Bite != n) { + Reset(); + return false; } - data += bite; - done += bite; - todo -= bite; - ac3todo -= bite; + Bite = packetLen - pesHeaderLen; + n = ResultBuffer->Put(Data, Bite); + if (Bite != n) { + Reset(); + Done += n; + return false; + } + // ac3 frame completely processed? + if (Bite >= ac3todo) + state = find_0b; // go on with finding start of next packet } + else { + fragmentTodo = packetLen; + // copy the pesheader into separate buffer for later processing + if (fragmentLen + Bite > (int)sizeof(fragmentData)) { + Reset(); + return false; + } + memcpy(fragmentData + fragmentLen, pesHeader, Bite); + fragmentLen += Bite; + fragmentTodo -= Bite; + // copy the fragment into separate buffer for later processing + Bite = Todo; + if (fragmentLen + Bite > (int)sizeof(fragmentData)) { + Reset(); + return false; + } + memcpy(fragmentData + fragmentLen, Data, Bite); + fragmentLen += Bite; + fragmentTodo -= Bite; + } + return true; +} + +int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) +{ + // check for MPEG 2 + if ((Data[6] & 0xC0) != 0x80) + return 0; + // skip PES header + int done = 6 + 3 + Data[8]; + int todo = Count - done; + const uchar *data = Data + done; + bool headerCopied = false; + // look for 0x0B 0x77 <chk1> <chk2> <frameSize> while (todo > 0) { switch (state) { case find_0b: - if (*data == 0x0B) + if (*data == 0x0B) { ++(int &)state; + // copy header information once for later use + if (!headerCopied) { + headerCopied = true; + pesHeaderLen = 6 + 3 + Data[8]; + memcpy(pesHeader, Data, pesHeaderLen); + AppendSubStreamID(); + } + } data++; done++; todo--; @@ -191,10 +274,13 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int todo--; ++(int &)state; continue; - case get_length: { + case get_length: ac3todo = 2 * frameSizes[*data]; // frameSizeCode was invalid => restart searching if (ac3todo <= 0) { + // reset PES header instead of using/copying a wrong one + ResetPesHeader(); + headerCopied = true; if (chk1 == 0x0B) { if (chk2 == 0x77) { state = store_chk1; @@ -214,62 +300,32 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int state = find_0b; continue; } - // adjust PES packet length and output packet - if (subStreamId) { - pesHeader[pesHeaderLen++] = subStreamId; - pesHeader[pesHeaderLen++] = 0x00; - pesHeader[pesHeaderLen++] = 0x00; - pesHeader[pesHeaderLen++] = 0x00; - } - int packetLen = pesHeaderLen - 6 + ac3todo; - pesHeader[4] = packetLen >> 8; - pesHeader[5] = packetLen & 0xFF; - pesHeader[pesHeaderLen + 0] = 0x0B; - pesHeader[pesHeaderLen + 1] = 0x77; - pesHeader[pesHeaderLen + 2] = chk1; - pesHeader[pesHeaderLen + 3] = chk2; + // append read data to header for common output processing + pesHeader[pesHeaderLen++] = 0x0B; + pesHeader[pesHeaderLen++] = 0x77; + pesHeader[pesHeaderLen++] = chk1; + pesHeader[pesHeaderLen++] = chk2; ac3todo -= 4; - int bite = pesHeaderLen + 4; - // enough data available to put PES packet into buffer? - if (ac3todo <= todo) { - int n = ResultBuffer->Put(pesHeader, bite); - if (bite != n) { - Reset(); + ++(int &)state; + // fall through to output + case output_packet: { + int bite = 0; + // finish remainder of ac3 frame? + if (fragmentTodo > 0) { + if (!FinishRemainder(ResultBuffer, data, todo, done, bite)) return done; - } - bite = ac3todo; - n = ResultBuffer->Put(data, bite); - if (bite != n) { - Reset(); - return done + n; - } } else { - // copy the fragment into separate buffer for later processing - if (fragmentLen + bite > (int)sizeof(fragmentData)) { - Reset(); - return done; - } - memcpy(fragmentData + fragmentLen, pesHeader, bite); - fragmentLen += bite; - bite = todo; - if (fragmentLen + bite > (int)sizeof(fragmentData)) { - Reset(); + // start a new packet + if (!StartNewPacket(ResultBuffer, data, todo, done, bite)) return done; - } - memcpy(fragmentData + fragmentLen, data, bite); - fragmentLen += bite; + // prepare for next packet + ResetPesHeader(); } data += bite; done += bite; todo -= bite; ac3todo -= bite; - // prepare for next packet - pesHeader[6] = 0x80; - pesHeader[7] = 0x00; - pesHeader[8] = 0x00; - pesHeaderLen = 9; - state = find_0b; } } } @@ -294,7 +350,7 @@ int cDolbyRepacker::BreakAt(const uchar *Data, int Count) const uchar *data = Data + headerLen; // break after ac3 frame? if (data[0] == 0x0B && data[1] == 0x77 && frameSizes[data[4]] > 0) - return headerLen + frameSizes[data[4]]; + return headerLen + 2 * frameSizes[data[4]]; return -1; } @@ -392,8 +448,10 @@ cTS2PES::cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t Aud audioCid = AudioCid; subStreamId = SubStreamId; repacker = Repacker; - if (repacker) + if (repacker) { + repacker->SetMaxPacketSize(size); repacker->SetSubStreamId(subStreamId); + } tsErrors = 0; ccErrors = 0; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 1.21 2004/12/26 12:35:33 kls Exp $ + * $Id: timers.c 1.22 2005/02/06 09:45:52 kls Exp $ */ #include "timers.h" @@ -112,7 +112,7 @@ cString cTimer::ToText(bool UseChannelID) asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : ""); strreplace(summary, '|', '\n'); strreplace(file, '|', ':'); - return buffer; + return cString(buffer, true); } int cTimer::TimeToInt(int t) @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 1.88 2005/01/16 11:47:44 kls Exp $ + * $Id: tools.c 1.89 2005/02/05 10:10:30 kls Exp $ */ #include "tools.h" @@ -199,7 +199,7 @@ cString strescape(const char *s, const char *chars) } if (t) *t = 0; - return s; + return cString(s, t != NULL); } bool startswith(const char *s, const char *p) @@ -250,7 +250,7 @@ cString AddDirectory(const char *DirName, const char *FileName) { char *buf; asprintf(&buf, "%s/%s", DirName && *DirName ? DirName : ".", FileName); - return buf; + return cString(buf, true); } cString itoa(int n) @@ -513,9 +513,9 @@ uint64 cTimeMs::Elapsed(void) // --- cString --------------------------------------------------------------- -cString::cString(const char *S) +cString::cString(const char *S, bool TakePointer) { - s = S ? strdup(S) : NULL; + s = TakePointer ? (char *)S : S ? strdup(S) : NULL; } cString::~cString() @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 1.65 2005/01/16 11:39:58 kls Exp $ + * $Id: tools.h 1.66 2005/02/05 10:00:22 kls Exp $ */ #ifndef __TOOLS_H @@ -61,7 +61,7 @@ class cString { private: char *s; public: - cString(const char *S = NULL); + cString(const char *S = NULL, bool TakePointer = false); virtual ~cString(); operator const char * () const { return s; } // for use in (const char *) context const char * operator*() const { return s; } // for use in (const void *) context (printf() etc.) @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/vdr * - * $Id: vdr.c 1.200 2005/01/14 16:50:39 kls Exp $ + * $Id: vdr.c 1.201 2005/01/30 14:15:50 kls Exp $ */ #include <getopt.h> @@ -928,6 +928,7 @@ int main(int argc, char *argv[]) Exit: + PluginManager.StopPlugins(); cRecordControls::Shutdown(); cCutter::Stop(); delete Menu; @@ -941,7 +942,7 @@ Exit: Setup.CurrentVolume = cDevice::CurrentVolume(); Setup.Save(); cDevice::Shutdown(); - PluginManager.Shutdown(true); + PluginManager.Shutdown(); ReportEpgBugFixStats(); if (WatchdogTimeout > 0) dsyslog("max. latency time %d seconds", MaxLatencyTime); |