1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Implemented audio track menu

This commit is contained in:
Klaus Schmidinger 2005-01-02 15:11:44 +01:00
parent 286af66cfb
commit 0b3a801ab4
27 changed files with 799 additions and 94 deletions

16
HISTORY
View File

@ -3160,7 +3160,7 @@ Video Disk Recorder Revision History
right day of week for timers in the future. right day of week for timers in the future.
- Some improvements to cPoller (thanks to Marco Schlüßler). - Some improvements to cPoller (thanks to Marco Schlüßler).
2004-12-26: Version 1.3.18 2005-01-02: Version 1.3.18
- Removed an unused variable from cTimer::GetWDayFromMDay() (thanks to Wayne Keer - Removed an unused variable from cTimer::GetWDayFromMDay() (thanks to Wayne Keer
for reporting this one). for reporting this one).
@ -3251,3 +3251,17 @@ Video Disk Recorder Revision History
Zocholl for pointing out this problem). Zocholl for pointing out this problem).
- Added cDevice::mutexReceiver to avoid a race condition when attaching/detaching - Added cDevice::mutexReceiver to avoid a race condition when attaching/detaching
receivers from different threads. receivers from different threads.
- The new remote control button "Audio" can be used to switch between different
audio tracks. The "Green" button in the "Main" menu has been changed from "Language"
to "Audio", since it now also controls switching between normal and Dolby Digital
audio tracks.
- The description of the audio tracks is now taken from the "component descriptors"
that are broadcast in the EPG data. However (as no big surprise), not all channels
actually provide useful data here, so there are now some additional EPG bugfixes,
which can be activated by setting the "EPG bugfix level" to 3.
- The format of the 'epg.data' files has been extended by the new tag 'X', which
contains the stream components of an event (see man vdr(5) for details).
- The cStatus class now has the new member function SetAudioTrack(), which can be
used to get notified when the audio track has been switched.
- Skins need to implement the new cSkinDisplayTrack class to display the audio
track menu.

26
MANUAL
View File

@ -21,7 +21,7 @@ Version 1.2
Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu on Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu on
Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu
Red - Record Edit Edit ABC/abc Play/Commands(2) Jump Red - Record Edit Edit ABC/abc Play/Commands(2) Jump
Green - Language New New Ins/Ovr Rewind Skip -60s Green - Audio New New Ins/Ovr Rewind Skip -60s
Yellow - Pause live Delete Delete Delete Delete Skip +60s Yellow - Pause live Delete Delete Delete Delete Skip +60s
Blue - Stop/Resume Mark On/Off(1) - Summary Stop Blue - Stop/Resume Mark On/Off(1) - Summary Stop
0..9 Ch select - Sort(3) Day(4) Numeric inp. Exec cmd(2) Editing 0..9 Ch select - Sort(3) Day(4) Numeric inp. Exec cmd(2) Editing
@ -49,6 +49,8 @@ Version 1.2
Volume- volume down Volume- volume down
Mute mute Mute mute
Audio select audio track
Schedule \ Schedule \
Channels | Channels |
Timers | directly access the VDR Timers | directly access the VDR
@ -187,15 +189,16 @@ Version 1.2
To bring up the channel display without switching channels you can press To bring up the channel display without switching channels you can press
the "Ok" button. the "Ok" button.
* Selecting language specific audio track * Selecting audio tracks
If the current channel provides different audio tracks (typically for If the current channel or recording provides different audio tracks (for
different languages), the "Green" button in the "VDR" menu can be pressed different languages or Dolby Digital), the "Green" button in the "VDR" menu can
to toggle between these. There can be two different audio PIDs per channel, be pressed to bring up the "Audio" menu. Within this menu, the "Up" and "Down"
assuming that typically a channel broadcasts a country specific language keys can be used to switch between the audio tracks. If your remote control has
plus the movie's original soundtrack. a dedicated "Audio" button, the first press of that button brings up the "Audio"
Recordings made form such channels will contain both audio tracks, and when menu, and every further press switches to the next available audio track.
replaying the desired audio track can be selected the same way. The "Audio" menu will automatically disappear after 5 seconds of user inactivity,
or if any key other than the ones described above is pressed.
* Switching through channel groups * Switching through channel groups
@ -495,14 +498,15 @@ Version 1.2
A value of '0' completely turns off scanning on both single A value of '0' completely turns off scanning on both single
and multiple card systems. and multiple card systems.
EPG bugfix level = 2 Some tv stations transmit weirdly formatted EPG data. EPG bugfix level = 3 Some tv stations transmit weirdly formatted EPG data.
VDR attempts to fix these bugs up to the given level: VDR attempts to fix these bugs up to the given level:
0 = no EPG fixing 0 = no EPG fixing
1 = basic fixing of text location (Title, Episode and 1 = basic fixing of text location (Title, Episode and
Extended Description) Extended Description)
2 = removal of excess whitespace and hyphens, mapping of 2 = removal of excess whitespace and hyphens, mapping of
wrongly used characters wrongly used characters
Default is '2'. 3 = fix stream component descriptions
Default is '3'.
Note that after changing the setting of this parameter Note that after changing the setting of this parameter
any EPG data that has already been received will remain any EPG data that has already been received will remain
in its existing format - only newly received data will in its existing format - only newly received data will

View File

@ -1362,6 +1362,9 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void); virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly); virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void); virtual cSkinDisplayVolume *DisplayVolume(void);
<!--X1.3.18--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
virtual cSkinDisplayMessage *DisplayTrack(int NumTracks, const char * const *Tracks);
<!--X1.3.18--></td></tr></table>
virtual cSkinDisplayMessage *DisplayMessage(void); virtual cSkinDisplayMessage *DisplayMessage(void);
}; };
</pre></td></tr></table><p> </pre></td></tr></table><p>

View File

@ -9,6 +9,7 @@ VDR Plugin 'skincurses' Revision History
- Fixed some default parameters. - Fixed some default parameters.
2004-12-26: Version 0.0.3 2005-01-02: Version 0.0.3
- Made several functions threadsafe. - Made several functions threadsafe.
- New audio track display.

View File

@ -3,7 +3,7 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: skincurses.c 1.3 2004/12/26 11:36:35 kls Exp $ * $Id: skincurses.c 1.4 2005/01/02 15:11:29 kls Exp $
*/ */
#include <ncurses.h> #include <ncurses.h>
@ -558,6 +558,68 @@ void cSkinCursesDisplayVolume::Flush(void)
osd->Flush(); osd->Flush();
} }
// --- cSkinCursesDisplayTracks ----------------------------------------------
class cSkinCursesDisplayTracks : public cSkinDisplayTracks {
private:
cOsd *osd;
int itemsWidth;
int currentIndex;
void SetItem(const char *Text, int Index, bool Current);
public:
cSkinCursesDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual ~cSkinCursesDisplayTracks();
virtual void SetTrack(int Index, const char * const *Tracks);
virtual void Flush(void);
};
cSkinCursesDisplayTracks::cSkinCursesDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
currentIndex = -1;
itemsWidth = Font.Width(Title);
for (int i = 0; i < NumTracks; i++)
itemsWidth = max(itemsWidth, Font.Width(Tracks[i]));
itemsWidth = min(itemsWidth, OsdWidth);
osd = new cCursesOsd(0, 0);
osd->DrawRectangle(0, 0, OsdWidth - 1, OsdHeight - 1, clrBackground);
osd->DrawText(0, 0, Title, clrBlack, clrCyan, &Font, itemsWidth);
for (int i = 0; i < NumTracks; i++)
SetItem(Tracks[i], i, false);
}
cSkinCursesDisplayTracks::~cSkinCursesDisplayTracks()
{
delete osd;
}
void cSkinCursesDisplayTracks::SetItem(const char *Text, int Index, bool Current)
{
int y = 1 + Index;
int ColorFg, ColorBg;
if (Current) {
ColorFg = clrBlack;
ColorBg = clrCyan;
currentIndex = Index;
}
else {
ColorFg = clrWhite;
ColorBg = clrBackground;
}
osd->DrawText(0, y, Text, ColorFg, ColorBg, &Font, itemsWidth);
}
void cSkinCursesDisplayTracks::SetTrack(int Index, const char * const *Tracks)
{
if (currentIndex >= 0)
SetItem(Tracks[currentIndex], currentIndex, false);
SetItem(Tracks[Index], Index, true);
}
void cSkinCursesDisplayTracks::Flush(void)
{
osd->Flush();
}
// --- cSkinCursesDisplayMessage --------------------------------------------- // --- cSkinCursesDisplayMessage ---------------------------------------------
class cSkinCursesDisplayMessage : public cSkinDisplayMessage { class cSkinCursesDisplayMessage : public cSkinDisplayMessage {
@ -600,6 +662,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void); virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly); virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void); virtual cSkinDisplayVolume *DisplayVolume(void);
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual cSkinDisplayMessage *DisplayMessage(void); virtual cSkinDisplayMessage *DisplayMessage(void);
}; };
@ -633,6 +696,11 @@ cSkinDisplayVolume *cSkinCurses::DisplayVolume(void)
return new cSkinCursesDisplayVolume; return new cSkinCursesDisplayVolume;
} }
cSkinDisplayTracks *cSkinCurses::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
return new cSkinCursesDisplayTracks(Title, NumTracks, Tracks);
}
cSkinDisplayMessage *cSkinCurses::DisplayMessage(void) cSkinDisplayMessage *cSkinCurses::DisplayMessage(void)
{ {
return new cSkinCursesDisplayMessage; return new cSkinCursesDisplayMessage;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.c 1.64 2004/12/24 15:37:11 kls Exp $ * $Id: device.c 1.65 2005/01/02 14:08:40 kls Exp $
*/ */
#include "device.h" #include "device.h"
@ -604,15 +604,19 @@ void cDevice::ClrAvailableTracks(void)
memset(availableTracks, 0, sizeof(availableTracks)); memset(availableTracks, 0, sizeof(availableTracks));
} }
bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, uint32_t Flags) bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description, uint32_t Flags)
{ {
eTrackType t = eTrackType(Type + Index); eTrackType t = eTrackType(Type + Index);
if ((Type == ttAudio && IS_AUDIO_TRACK(t)) || if ((Type == ttAudio && IS_AUDIO_TRACK(t)) ||
(Type == ttDolby && IS_DOLBY_TRACK(t))) { (Type == ttDolby && IS_DOLBY_TRACK(t))) {
if (Language) if (Language)
strn0cpy(availableTracks[t].language, Language, sizeof(availableTracks[t].language)); 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; availableTracks[t].flags = Flags;
availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking
}
return true; return true;
} }
else else
@ -652,21 +656,6 @@ bool cDevice::SetCurrentAudioTrack(eTrackType Type)
return false; return false;
} }
bool cDevice::IncCurrentAudioTrack(void)
{
int i = currentAudioTrack + 1;
for (;;) {
if (i > ttDolbyLast)
i = ttAudioFirst;
if (i == currentAudioTrack)
break;
if (availableTracks[i].id)
return SetCurrentAudioTrack(eTrackType(i));
i++;
}
return false;
}
bool cDevice::CanReplay(void) const bool cDevice::CanReplay(void) const
{ {
return HasDecoder(); return HasDecoder();

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.h 1.48 2004/12/24 14:57:24 kls Exp $ * $Id: device.h 1.49 2005/01/02 14:08:36 kls Exp $
*/ */
#ifndef __DEVICE_H #ifndef __DEVICE_H
@ -77,6 +77,7 @@ enum eTrackType { ttNone,
struct tTrackId { struct tTrackId {
uint16_t id; // The PES packet id or the PID. uint16_t id; // The PES packet id or the PID.
char language[8]; // something like either "eng" or "deu/eng" char language[8]; // something like either "eng" or "deu/eng"
char description[32]; // something like "Dolby Digital 5.1"
// for future use: // for future use:
uint32_t flags; // Used to further identify the actual track. uint32_t flags; // Used to further identify the actual track.
}; };
@ -319,10 +320,12 @@ protected:
///< Sets the current audio track to the given value. ///< Sets the current audio track to the given value.
public: public:
void ClrAvailableTracks(void); void ClrAvailableTracks(void);
bool SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language = NULL, uint32_t Flags = 0); bool SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language = NULL, const char *Description = NULL, uint32_t Flags = 0);
///< Sets the track of the given Type and Index to the given values. ///< 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. ///< Type must be one of the basic eTrackType values, like ttAudio or ttDolby.
///< Index tells which track of the given basic type is meant. ///< 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
///< given Language and Description will be set.
///< \return Returns true if the track was set correctly, false otherwise. ///< \return Returns true if the track was set correctly, false otherwise.
const tTrackId *GetTrack(eTrackType Type); const tTrackId *GetTrack(eTrackType Type);
///< Returns a pointer to the given track id, or NULL if Type is not ///< Returns a pointer to the given track id, or NULL if Type is not
@ -335,10 +338,6 @@ public:
bool SetCurrentAudioTrack(eTrackType Type); bool SetCurrentAudioTrack(eTrackType Type);
///< Sets the current audio track to the given Type. ///< Sets the current audio track to the given Type.
///< \return Returns true if Type is a valid audio track, false otherwise. ///< \return Returns true if Type is a valid audio track, false otherwise.
bool IncCurrentAudioTrack(void);
///< Sets the current audio track to the next available track (wraps to
///< to the first one if necessary).
///< \return Returns true if the audio track has been changed, false otherwise.
// Audio facilities // Audio facilities

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.c 1.107 2004/12/17 14:19:48 kls Exp $ * $Id: dvbdevice.c 1.108 2005/01/02 11:51:18 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -860,10 +860,8 @@ void cDvbDevice::SetAudioTrackDevice(eTrackType Type)
else if (IS_DOLBY_TRACK(Type)) { else if (IS_DOLBY_TRACK(Type)) {
// Currently this works only in Transfer Mode // Currently this works only in Transfer Mode
cChannel *Channel = Channels.GetByNumber(CurrentChannel()); cChannel *Channel = Channels.GetByNumber(CurrentChannel());
if (Channel) { if (Channel)
SetChannelDevice(Channel, false); SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid(0), Channel->Apid(1), Channel->Dpid(0), Channel->Dpid(1)));
}
} }
} }
} }

32
eit.c
View File

@ -8,7 +8,7 @@
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>. * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
* *
* $Id: eit.c 1.101 2004/12/26 10:38:46 kls Exp $ * $Id: eit.c 1.102 2005/01/02 11:52:12 kls Exp $
*/ */
#include "eit.h" #include "eit.h"
@ -91,6 +91,8 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL; SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL;
SI::ShortEventDescriptor *ShortEventDescriptor = NULL; SI::ShortEventDescriptor *ShortEventDescriptor = NULL;
cLinkChannels *LinkChannels = NULL; cLinkChannels *LinkChannels = NULL;
int NumComponents = 0;
SI::ComponentDescriptor *ComponentDescriptors[MAXCOMPONENTS];
for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) { for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) {
switch (d->getDescriptorTag()) { switch (d->getDescriptorTag()) {
case SI::ExtendedEventDescriptorTag: { case SI::ExtendedEventDescriptorTag: {
@ -186,6 +188,20 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
} }
} }
break; break;
case SI::ComponentDescriptorTag: {
SI::ComponentDescriptor *cd = (SI::ComponentDescriptor *)d;
uchar Stream = cd->getStreamContent();
uchar Type = cd->getComponentType();
if (1 <= Stream && Stream <= 2 && Type != 0) {
if (NumComponents < MAXCOMPONENTS) {
ComponentDescriptors[NumComponents++] = cd;
d = NULL; // so that it is not deleted
}
else
dsyslog("more than %d component descriptors!", MAXCOMPONENTS);
}
}
break;
default: ; default: ;
} }
delete d; delete d;
@ -205,8 +221,20 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
delete ExtendedEventDescriptors; delete ExtendedEventDescriptors;
delete ShortEventDescriptor; delete ShortEventDescriptor;
pEvent->FixEpgBugs(); if (NumComponents > 0) {
cComponents *Components = new cComponents(NumComponents);
for (int i = 0; i < NumComponents; i++) {
char buffer[256];
SI::ComponentDescriptor *cd = ComponentDescriptors[i];
Components->SetComponent(i, cd->getStreamContent(), cd->getComponentType(), I18nNormalizeLanguageCode(cd->languageCode), cd->description.getText(buffer, sizeof(buffer)));
delete cd;
}
pEvent->SetComponents(Components);
}
else
pEvent->SetComponents(NULL);
pEvent->FixEpgBugs();
if (LinkChannels) if (LinkChannels)
channel->SetLinkChannels(LinkChannels); channel->SetLinkChannels(LinkChannels);
if (Tid == 0x4E) { // we trust only the present/following info on the actual TS if (Tid == 0x4E) { // we trust only the present/following info on the actual TS

165
epg.c
View File

@ -7,7 +7,7 @@
* Original version (as used in VDR before 1.3.0) written by * Original version (as used in VDR before 1.3.0) written by
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
* *
* $Id: epg.c 1.23 2004/12/26 11:32:01 kls Exp $ * $Id: epg.c 1.24 2005/01/02 11:25:25 kls Exp $
*/ */
#include "epg.h" #include "epg.h"
@ -16,6 +16,66 @@
#include <ctype.h> #include <ctype.h>
#include <time.h> #include <time.h>
// --- tComponent ------------------------------------------------------------
cString tComponent::ToString(void)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "%X %02X %-3s %s", stream, type, language, description ? description : "");
return buffer;
}
bool tComponent::FromString(const char *s)
{
unsigned int Stream, Type;
int n = sscanf(s, "%X %02X %3c %a[^\n]", &Stream, &Type, language, &description);
if (n != 4)
description = NULL;
else if (isempty(description)) {
free(description);
description = NULL;
}
stream = Stream;
type = Type;
return n >= 3;
}
// --- cComponents -----------------------------------------------------------
cComponents::cComponents(int NumComponents)
{
numComponents = NumComponents;
components = MALLOC(tComponent, numComponents);
memset(components, 0, sizeof(tComponent) * numComponents);
}
cComponents::~cComponents(void)
{
for (int i = 0; i < numComponents; i++)
free(components[i].description);
free(components);
}
bool cComponents::SetComponent(int Index, const char *s)
{
if (Index < numComponents)
return components[Index].FromString(s);
return false;
}
bool cComponents::SetComponent(int Index, uchar Stream, uchar Type, const char *Language, const char *Description)
{
if (Index < numComponents) {
tComponent *p = &components[Index];
p->stream = Stream;
p->type = Type;
strn0cpy(p->language, Language, sizeof(p->language));
p->description = strcpyrealloc(p->description, !isempty(Description) ? Description : NULL);
return true;
}
return false;
}
// --- cEvent ---------------------------------------------------------------- // --- cEvent ----------------------------------------------------------------
cEvent::cEvent(tChannelID ChannelID, u_int16_t EventID) cEvent::cEvent(tChannelID ChannelID, u_int16_t EventID)
@ -28,6 +88,7 @@ cEvent::cEvent(tChannelID ChannelID, u_int16_t EventID)
title = NULL; title = NULL;
shortText = NULL; shortText = NULL;
description = NULL; description = NULL;
components = NULL;
startTime = 0; startTime = 0;
duration = 0; duration = 0;
vps = 0; vps = 0;
@ -39,6 +100,7 @@ cEvent::~cEvent()
free(title); free(title);
free(shortText); free(shortText);
free(description); free(description);
delete components;
} }
int cEvent::Compare(const cListObject &ListObject) const int cEvent::Compare(const cListObject &ListObject) const
@ -85,6 +147,12 @@ void cEvent::SetDescription(const char *Description)
description = strcpyrealloc(description, Description); description = strcpyrealloc(description, Description);
} }
void cEvent::SetComponents(cComponents *Components)
{
delete components;
components = Components;
}
void cEvent::SetStartTime(time_t StartTime) void cEvent::SetStartTime(time_t StartTime)
{ {
startTime = StartTime; startTime = StartTime;
@ -168,6 +236,12 @@ void cEvent::Dump(FILE *f, const char *Prefix) const
fprintf(f, "%sD %s\n", Prefix, description); fprintf(f, "%sD %s\n", Prefix, description);
strreplace(description, '|', '\n'); strreplace(description, '|', '\n');
} }
if (components) {
for (int i = 0; i < components->NumComponents(); i++) {
tComponent *p = components->Component(i);
fprintf(f, "%sX %s\n", Prefix, *p->ToString());
}
}
if (vps) if (vps)
fprintf(f, "%sV %ld\n", Prefix, vps); fprintf(f, "%sV %ld\n", Prefix, vps);
fprintf(f, "%se\n", Prefix); fprintf(f, "%se\n", Prefix);
@ -178,6 +252,8 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
{ {
if (Schedule) { if (Schedule) {
cEvent *Event = NULL; cEvent *Event = NULL;
int NumComponents = 0;
char *ComponentStrings[MAXCOMPONENTS];
char *s; char *s;
cReadLine ReadLine; cReadLine ReadLine;
while ((s = ReadLine.Read(f)) != NULL) { while ((s = ReadLine.Read(f)) != NULL) {
@ -199,6 +275,7 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
Event->SetDuration(Duration); Event->SetDuration(Duration);
} }
} }
NumComponents = 0;
} }
break; break;
case 'T': if (Event) case 'T': if (Event)
@ -212,10 +289,26 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
Event->SetDescription(t); Event->SetDescription(t);
} }
break; break;
case 'X': if (Event) {
if (NumComponents < MAXCOMPONENTS)
ComponentStrings[NumComponents++] = strdup(t);
else
dsyslog("more than %d component descriptors!", MAXCOMPONENTS);
}
break;
case 'V': if (Event) case 'V': if (Event)
Event->SetVps(atoi(t)); Event->SetVps(atoi(t));
break; break;
case 'e': Event = NULL; case 'e': if (Event && NumComponents > 0) {
cComponents *Components = new cComponents(NumComponents);
for (int i = 0; i < NumComponents; i++) {
if (!Components->SetComponent(i, ComponentStrings[i]))
esyslog("ERROR: faulty component string in EPG data: '%s'", ComponentStrings[i]);
free(ComponentStrings[i]);
}
Event->SetComponents(Components);
}
Event = NULL;
break; break;
case 'c': // to keep things simple we react on 'c' here case 'c': // to keep things simple we react on 'c' here
return true; return true;
@ -228,7 +321,7 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
return false; return false;
} }
#define MAXEPGBUGFIXSTATS 8 #define MAXEPGBUGFIXSTATS 12
#define MAXEPGBUGFIXCHANS 100 #define MAXEPGBUGFIXCHANS 100
struct tEpgBugFixStats { struct tEpgBugFixStats {
int hits; int hits;
@ -476,6 +569,72 @@ void cEvent::FixEpgBugs(void)
strreplace(title, '`', '\''); strreplace(title, '`', '\'');
strreplace(shortText, '`', '\''); strreplace(shortText, '`', '\'');
strreplace(description, '`', '\''); strreplace(description, '`', '\'');
if (Setup.EPGBugfixLevel <= 2)
return;
// The stream components have a "description" field which some channels
// apparently have no idea of how to set correctly:
if (components) {
for (int i = 0; i < components->NumComponents(); i++) {
tComponent *p = components->Component(i);
switch (p->stream) {
case 0x01: { // video
if (p->description) {
if (strcasecmp(p->description, "Video") == 0 ||
strcasecmp(p->description, "Bildformat") == 0) {
// Yes, we know it's video - that's what the 'stream' code
// is for! But _which_ video is it?
free(p->description);
p->description = NULL;
EpgBugFixStat(8, ChannelID());
}
}
if (!p->description) {
switch (p->type) {
case 0x01:
case 0x05: p->description = strdup("4:3"); break;
case 0x02:
case 0x03:
case 0x06:
case 0x07: p->description = strdup("16:9"); break;
case 0x04:
case 0x08: p->description = strdup(">16:9"); break;
case 0x09:
case 0x0D: p->description = strdup("HD 4:3"); break;
case 0x0A:
case 0x0B:
case 0x0E:
case 0x0F: p->description = strdup("HD 16:9"); break;
case 0x0C:
case 0x10: p->description = strdup("HD >16:9"); break;
}
EpgBugFixStat(9, ChannelID());
}
}
break;
case 0x02: { // audio
if (p->description) {
if (strcasecmp(p->description, "Audio") == 0) {
// Yes, we know it's audio - that's what the 'stream' code
// is for! But _which_ audio is it?
free(p->description);
p->description = NULL;
EpgBugFixStat(10, ChannelID());
}
}
if (!p->description) {
switch (p->type) {
case 0x05: p->description = strdup("Dolby Digital"); break;
// all others will just display the language
}
EpgBugFixStat(11, ChannelID());
}
}
break;
}
}
}
} }
} }

30
epg.h
View File

@ -7,7 +7,7 @@
* Original version (as used in VDR before 1.3.0) written by * Original version (as used in VDR before 1.3.0) written by
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
* *
* $Id: epg.h 1.18 2004/12/26 11:31:27 kls Exp $ * $Id: epg.h 1.19 2005/01/02 10:44:41 kls Exp $
*/ */
#ifndef __EPG_H #ifndef __EPG_H
@ -17,10 +17,33 @@
#include "thread.h" #include "thread.h"
#include "tools.h" #include "tools.h"
#define MAXEPGBUGFIXLEVEL 2 #define MAXEPGBUGFIXLEVEL 3
#define MAXCOMPONENTS 32
enum eDumpMode { dmAll, dmPresent, dmFollowing, dmAtTime }; enum eDumpMode { dmAll, dmPresent, dmFollowing, dmAtTime };
struct tComponent {
uchar stream;
uchar type;
char language[4];
char *description;
cString ToString(void);
bool FromString(const char *s);
};
class cComponents {
private:
int numComponents;
tComponent *components;
public:
cComponents(int NumComponents);
~cComponents(void);
int NumComponents(void) const { return numComponents; }
bool SetComponent(int Index, const char *s);
bool SetComponent(int Index, uchar Stream, uchar Type, const char *Language, const char *Description);
tComponent *Component(int Index) const { return (Index < numComponents) ? &components[Index] : NULL; }
};
class cSchedule; class cSchedule;
class cEvent : public cListObject { class cEvent : public cListObject {
@ -33,6 +56,7 @@ private:
char *title; // Title of this event char *title; // Title of this event
char *shortText; // Short description of this event (typically the episode name in case of a series) char *shortText; // Short description of this event (typically the episode name in case of a series)
char *description; // Description of this event char *description; // Description of this event
cComponents *components; // The stream components of this event (separated by '\n')
time_t startTime; // Start time of this event time_t startTime; // Start time of this event
int duration; // Duration of this event in seconds int duration; // Duration of this event in seconds
time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL) time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL)
@ -49,6 +73,7 @@ public:
const char *Title(void) const { return title; } const char *Title(void) const { return title; }
const char *ShortText(void) const { return shortText; } const char *ShortText(void) const { return shortText; }
const char *Description(void) const { return description; } const char *Description(void) const { return description; }
const cComponents *Components(void) const { return components; }
time_t StartTime(void) const { return startTime; } time_t StartTime(void) const { return startTime; }
time_t EndTime(void) const { return startTime + duration; } time_t EndTime(void) const { return startTime + duration; }
int Duration(void) const { return duration; } int Duration(void) const { return duration; }
@ -67,6 +92,7 @@ public:
void SetTitle(const char *Title); void SetTitle(const char *Title);
void SetShortText(const char *ShortText); void SetShortText(const char *ShortText);
void SetDescription(const char *Description); void SetDescription(const char *Description);
void SetComponents(cComponents *Components); // Will take ownership of Components!
void SetStartTime(time_t StartTime); void SetStartTime(time_t StartTime);
void SetDuration(int Duration); void SetDuration(int Duration);
void SetVps(time_t Vps); void SetVps(time_t Vps);

23
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: i18n.c 1.166 2004/12/18 16:44:24 kls Exp $ * $Id: i18n.c 1.167 2004/12/27 11:10:42 kls Exp $
* *
* Translations provided by: * Translations provided by:
* *
@ -4610,6 +4610,27 @@ const tI18nPhrase Phrases[] = {
"Hääletu", "Hääletu",
"Sluk lyd", "Sluk lyd",
}, },
{ "Audio",
"Audio",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
// Miscellaneous: // Miscellaneous:
{ "yes", { "yes",
"ja", "ja",

3
keys.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: keys.c 1.6 2004/12/19 11:25:47 kls Exp $ * $Id: keys.c 1.7 2004/12/27 11:08:34 kls Exp $
*/ */
#include "keys.h" #include "keys.h"
@ -44,6 +44,7 @@ static tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
{ kVolUp, "Volume+" }, { kVolUp, "Volume+" },
{ kVolDn, "Volume-" }, { kVolDn, "Volume-" },
{ kMute, "Mute" }, { kMute, "Mute" },
{ kAudio, "Audio" },
{ kSchedule, "Schedule" }, { kSchedule, "Schedule" },
{ kChannels, "Channels" }, { kChannels, "Channels" },
{ kTimers, "Timers" }, { kTimers, "Timers" },

3
keys.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: keys.h 1.5 2002/12/14 15:49:42 kls Exp $ * $Id: keys.h 1.6 2004/12/27 11:10:59 kls Exp $
*/ */
#ifndef __KEYS_H #ifndef __KEYS_H
@ -38,6 +38,7 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
kVolUp, kVolUp,
kVolDn, kVolDn,
kMute, kMute,
kAudio,
kSchedule, kSchedule,
kChannels, kChannels,
kTimers, kTimers,

124
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.323 2004/12/26 12:18:29 kls Exp $ * $Id: menu.c 1.324 2005/01/02 15:03:53 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -2410,7 +2410,7 @@ void cMenuMain::Set(const char *Plugin)
// Color buttons: // Color buttons:
SetHelp(!replaying ? tr("Record") : NULL, cDevice::PrimaryDevice()->NumAudioTracks() > 1 ? tr("Language") : NULL, replaying ? NULL : tr("Pause"), replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL); SetHelp(!replaying ? tr("Record") : NULL, cDevice::PrimaryDevice()->NumAudioTracks() > 1 ? tr("Audio") : NULL, replaying ? NULL : tr("Pause"), replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL);
Display(); Display();
lastActivity = time(NULL); lastActivity = time(NULL);
} }
@ -2471,9 +2471,11 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
state = replaying ? osContinue : osRecord; state = replaying ? osContinue : osRecord;
break; break;
case kGreen: if (!HadSubMenu) { case kGreen: if (!HadSubMenu) {
cDevice::PrimaryDevice()->IncCurrentAudioTrack(); if (cDevice::PrimaryDevice()->NumAudioTracks() > 1) {
cRemote::Put(kAudio, true);
state = osEnd; state = osEnd;
} }
}
break; break;
case kYellow: if (!HadSubMenu) case kYellow: if (!HadSubMenu)
state = replaying ? osContinue : osPause; state = replaying ? osContinue : osPause;
@ -2764,6 +2766,122 @@ eOSState cDisplayVolume::ProcessKey(eKeys Key)
return timeout.TimedOut() ? osEnd : osContinue; return timeout.TimedOut() ? osEnd : osContinue;
} }
// --- cDisplayTracks --------------------------------------------------------
#define TRACKTIMEOUT 5000 //ms
cDisplayTracks *cDisplayTracks::currentDisplayTracks = NULL;
cDisplayTracks::cDisplayTracks(void)
:cOsdObject(true)
{
// Get the actual audio track descriptions from the EPG if we're not replaying:
if (!cDevice::PrimaryDevice()->Replaying() || cTransferControl::ReceiverDevice()) {
cChannel *Channel = Channels.GetByNumber(cDevice::CurrentChannel());
if (Channel) {
cSchedulesLock SchedulesLock;
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
if (Schedules) {
const cSchedule *Schedule = Schedules->GetSchedule(Channel->GetChannelID());
if (Schedule) {
const cEvent *Present = Schedule->GetPresentEvent(true);
if (Present) {
const cComponents *Components = Present->Components();
if (Components) {
int indexAudio = 0;
int indexDolby = 0;
for (int i = 0; i < Components->NumComponents(); i++) {
const tComponent *p = Components->Component(i);
if (p->stream == 2) {
if (p->type == 0x05)
cDevice::PrimaryDevice()->SetAvailableTrack(ttDolby, indexDolby++, 0, NULL, p->description);
else
cDevice::PrimaryDevice()->SetAvailableTrack(ttAudio, indexAudio++, 0, NULL, p->description);
}
}
}
}
}
}
}
}
currentDisplayTracks = this;
numTracks = track = 0;
eTrackType CurrentAudioTrack = cDevice::PrimaryDevice()->GetCurrentAudioTrack();
for (int i = ttAudioFirst; i <= ttDolbyLast; i++) {
const tTrackId *TrackId = cDevice::PrimaryDevice()->GetTrack(eTrackType(i));
if (TrackId && TrackId->id) {
types[numTracks] = eTrackType(i);
descriptions[numTracks] = strdup(*TrackId->description ? TrackId->description : *TrackId->language ? TrackId->language : itoa(i));
if (i == CurrentAudioTrack)
track = numTracks;
numTracks++;
}
}
timeout.Set(TRACKTIMEOUT);
displayTracks = Skins.Current()->DisplayTracks(tr("Audio"), numTracks, descriptions);
Show();
}
cDisplayTracks::~cDisplayTracks()
{
delete displayTracks;
currentDisplayTracks = NULL;
for (int i = 0; i < numTracks; i++)
free(descriptions[i]);
cStatus::MsgOsdClear();
}
void cDisplayTracks::Show(void)
{
displayTracks->SetTrack(track, descriptions);
displayTracks->Flush();
cStatus::MsgSetAudioTrack(track, descriptions);
}
cDisplayTracks *cDisplayTracks::Create(void)
{
if (!currentDisplayTracks)
new cDisplayTracks;
return currentDisplayTracks;
}
void cDisplayTracks::Process(eKeys Key)
{
if (currentDisplayTracks)
currentDisplayTracks->ProcessKey(Key);
}
eOSState cDisplayTracks::ProcessKey(eKeys Key)
{
int oldTrack = track;
switch (Key) {
case kUp|k_Repeat:
case kUp:
case kDown|k_Repeat:
case kDown:
if (NORMALKEY(Key) == kUp && track > 0)
track--;
else if (NORMALKEY(Key) == kDown && track < numTracks - 1)
track++;
timeout.Set(TRACKTIMEOUT);
break;
case kAudio:
if (++track >= numTracks)
track = 0;
timeout.Set(TRACKTIMEOUT);
break;
case kNone: break;
default: return osEnd;
}
if (track != oldTrack) {
Show();
cDevice::PrimaryDevice()->SetCurrentAudioTrack(types[track]);
}
return timeout.TimedOut() ? osEnd : osContinue;
}
// --- cRecordControl -------------------------------------------------------- // --- cRecordControl --------------------------------------------------------
cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)

19
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.h 1.65 2004/12/19 17:59:47 kls Exp $ * $Id: menu.h 1.66 2005/01/02 14:38:00 kls Exp $
*/ */
#ifndef __MENU_H #ifndef __MENU_H
@ -75,6 +75,23 @@ public:
eOSState ProcessKey(eKeys Key); eOSState ProcessKey(eKeys Key);
}; };
class cDisplayTracks : public cOsdObject {
private:
cSkinDisplayTracks *displayTracks;
cTimeMs timeout;
eTrackType types[ttMaxTrackTypes];
char *descriptions[ttMaxTrackTypes];
int numTracks, track;
static cDisplayTracks *currentDisplayTracks;
virtual void Show(void);
cDisplayTracks(void);
public:
virtual ~cDisplayTracks();
static cDisplayTracks *Create(void);
static void Process(eKeys Key);
eOSState ProcessKey(eKeys Key);
};
class cMenuCam : public cOsdMenu { class cMenuCam : public cOsdMenu {
private: private:
cCiMenu *ciMenu; cCiMenu *ciMenu;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: player.h 1.13 2004/12/12 11:20:19 kls Exp $ * $Id: player.h 1.14 2004/12/30 10:44:34 kls Exp $
*/ */
#ifndef __PLAYER_H #ifndef __PLAYER_H
@ -19,7 +19,7 @@ private:
cDevice *device; cDevice *device;
ePlayMode playMode; ePlayMode playMode;
protected: protected:
bool DeviceSetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language = NULL, uint32_t Flags = 0) { return device ? device->SetAvailableTrack(Type, Index, Id, Language, Flags) : false; } 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 DevicePoll(cPoller &Poller, int TimeoutMs = 0) { return device ? device->Poll(Poller, TimeoutMs) : 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; } bool DeviceFlush(int TimeoutMs = 0) { return device ? device->Flush(TimeoutMs) : true; }
void DeviceTrickSpeed(int Speed) { if (device) device->TrickSpeed(Speed); } void DeviceTrickSpeed(int Speed) { if (device) device->TrickSpeed(Speed); }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skinclassic.c 1.9 2004/12/26 11:33:53 kls Exp $ * $Id: skinclassic.c 1.10 2005/01/02 14:41:08 kls Exp $
*/ */
#include "skinclassic.h" #include "skinclassic.h"
@ -502,6 +502,84 @@ void cSkinClassicDisplayVolume::Flush(void)
osd->Flush(); osd->Flush();
} }
// --- cSkinClassicDisplayTracks ---------------------------------------------
class cSkinClassicDisplayTracks : public cSkinDisplayTracks {
private:
cOsd *osd;
int x0, x1;
int y0, y1, y2;
int lineHeight;
int currentIndex;
void SetItem(const char *Text, int Index, bool Current);
public:
cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual ~cSkinClassicDisplayTracks();
virtual void SetTrack(int Index, const char * const *Tracks);
virtual void Flush(void);
};
cSkinClassicDisplayTracks::cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
const cFont *font = cFont::GetFont(fontOsd);
lineHeight = font->Height();
currentIndex = -1;
int ItemsWidth = font->Width(Title);
for (int i = 0; i < NumTracks; i++)
ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
ItemsWidth += 10;
x0 = 0;
x1 = Setup.OSDWidth;
int d = x1 - x0;
if (d > ItemsWidth) {
d = (d - ItemsWidth) & ~0x07; // must be multiple of 8
x1 -= d;
}
y0 = 0;
y1 = lineHeight;
y2 = y1 + NumTracks * lineHeight;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y2);
tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x1 - x0);
for (int i = 0; i < NumTracks; i++)
SetItem(Tracks[i], i, false);
}
cSkinClassicDisplayTracks::~cSkinClassicDisplayTracks()
{
delete osd;
}
void cSkinClassicDisplayTracks::SetItem(const char *Text, int Index, bool Current)
{
int y = y1 + Index * lineHeight;
tColor ColorFg, ColorBg;
if (Current) {
ColorFg = Theme.Color(clrMenuItemCurrentFg);
ColorBg = Theme.Color(clrMenuItemCurrentBg);
currentIndex = Index;
}
else {
ColorFg = Theme.Color(clrMenuItemSelectable);
ColorBg = Theme.Color(clrBackground);
}
const cFont *font = cFont::GetFont(fontOsd);
osd->DrawText(x0, y, Text, ColorFg, ColorBg, font, x1 - x0);
}
void cSkinClassicDisplayTracks::SetTrack(int Index, const char * const *Tracks)
{
if (currentIndex >= 0)
SetItem(Tracks[currentIndex], currentIndex, false);
SetItem(Tracks[Index], Index, true);
}
void cSkinClassicDisplayTracks::Flush(void)
{
osd->Flush();
}
// --- cSkinClassicDisplayMessage -------------------------------------------- // --- cSkinClassicDisplayMessage --------------------------------------------
class cSkinClassicDisplayMessage : public cSkinDisplayMessage { class cSkinClassicDisplayMessage : public cSkinDisplayMessage {
@ -571,6 +649,12 @@ cSkinDisplayVolume *cSkinClassic::DisplayVolume(void)
return new cSkinClassicDisplayVolume; return new cSkinClassicDisplayVolume;
} }
cSkinDisplayTracks *cSkinClassic::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
return new cSkinClassicDisplayTracks(Title, NumTracks, Tracks);
}
cSkinDisplayMessage *cSkinClassic::DisplayMessage(void) cSkinDisplayMessage *cSkinClassic::DisplayMessage(void)
{ {
return new cSkinClassicDisplayMessage; return new cSkinClassicDisplayMessage;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skinclassic.h 1.1 2004/04/18 09:38:02 kls Exp $ * $Id: skinclassic.h 1.2 2005/01/02 14:38:56 kls Exp $
*/ */
#ifndef __SKINCLASSIC_H #ifndef __SKINCLASSIC_H
@ -20,6 +20,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void); virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly); virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void); virtual cSkinDisplayVolume *DisplayVolume(void);
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual cSkinDisplayMessage *DisplayMessage(void); virtual cSkinDisplayMessage *DisplayMessage(void);
}; };

18
skins.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skins.h 1.4 2004/12/26 11:57:54 kls Exp $ * $Id: skins.h 1.5 2005/01/02 14:36:19 kls Exp $
*/ */
#ifndef __SKINS_H #ifndef __SKINS_H
@ -66,8 +66,6 @@ public:
Red = Video options Red = Video options
Green = Info now Green = Info now
Yellow = Info next Yellow = Info next
Blue = Audio options
AudioOptions
VideoOptions VideoOptions
*/ */
}; };
@ -223,6 +221,14 @@ public:
///< indicator shall be displayed. ///< indicator shall be displayed.
}; };
class cSkinDisplayTracks : public cSkinDisplay {
///< This class implements the track display.
public:
virtual void SetTrack(int Index, const char * const *Tracks) = 0;
///< Sets the current track to the one given by Index, which
///< points into the Tracks array of strings.
};
class cSkinDisplayMessage : public cSkinDisplay { class cSkinDisplayMessage : public cSkinDisplay {
///< This class implements a simple message display. ///< This class implements a simple message display.
public: public:
@ -275,6 +281,12 @@ public:
virtual cSkinDisplayVolume *DisplayVolume(void) = 0; virtual cSkinDisplayVolume *DisplayVolume(void) = 0;
///< Creates and returns a new object for displaying the current volume. ///< Creates and returns a new object for displaying the current volume.
///< The caller must delete the object after use. ///< The caller must delete the object after use.
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks) = 0;
///< Creates and returns a new object for displaying the available tracks.
///< NumTracks indicates how many entries in Tracks are available.
///< Tracks will be valid throughout the entire lifetime of the returned
///< cSkinDisplayTrack object.
///< The caller must delete the object after use.
virtual cSkinDisplayMessage *DisplayMessage(void) = 0; virtual cSkinDisplayMessage *DisplayMessage(void) = 0;
///< Creates and returns a new object for displaying a message. ///< Creates and returns a new object for displaying a message.
///< The caller must delete the object after use. ///< The caller must delete the object after use.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skinsttng.c 1.9 2004/12/26 11:34:29 kls Exp $ * $Id: skinsttng.c 1.10 2005/01/02 14:41:49 kls Exp $
*/ */
// Star Trek: The Next Generation® is a registered trademark of Paramount Pictures // Star Trek: The Next Generation® is a registered trademark of Paramount Pictures
@ -822,6 +822,140 @@ void cSkinSTTNGDisplayVolume::Flush(void)
osd->Flush(); osd->Flush();
} }
// --- cSkinSTTNGDisplayTracks -----------------------------------------------
class cSkinSTTNGDisplayTracks : public cSkinDisplayTracks {
private:
cOsd *osd;
int x0, x1, x2, x3, x4, x5, x6, x7;
int y0, y1, y2, y3, y4, y5, y6, y7;
int lineHeight;
tColor frameColor;
int currentIndex;
void SetItem(const char *Text, int Index, bool Current);
public:
cSkinSTTNGDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual ~cSkinSTTNGDisplayTracks();
virtual void SetTrack(int Index, const char * const *Tracks);
virtual void Flush(void);
};
cSkinSTTNGDisplayTracks::cSkinSTTNGDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
const cFont *font = cFont::GetFont(fontOsd);
lineHeight = font->Height();
frameColor = Theme.Color(clrMenuFrame);
currentIndex = -1;
int ItemsWidth = font->Width(Title);
for (int i = 0; i < NumTracks; i++)
ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
ItemsWidth += 10;
x0 = 0;
x1 = lineHeight / 2;
x3 = (x1 + Roundness + Gap + 7) & ~0x07; // must be multiple of 8
x2 = x3 - Gap;
x7 = Setup.OSDWidth;
x6 = x7 - lineHeight / 2;
x4 = (x6 - lineHeight / 2 - Gap) & ~0x07; // must be multiple of 8
x5 = x4 + Gap;
int d = x4 - x3;
if (d > ItemsWidth) {
d = (d - ItemsWidth) & ~0x07; // must be multiple of 8
x4 -= d;
x5 -= d;
x6 -= d;
x7 -= d;
}
y0 = 0;
y1 = lineHeight;
y2 = y1 + Roundness;
y3 = y2 + Gap;
// limit to Setup.OSDHeight? - what if height is too big???
y4 = y3 + NumTracks * lineHeight + 2 * Roundness;
y5 = y4 + Gap;
y6 = y5 + Roundness;
y7 = y6 + cFont::GetFont(fontSml)->Height();
int yt = (y0 + y1) / 2;
int yb = (y6 + y7) / 2;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y7);
tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 4 } };
if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x7 - 1, y3 - 1, 2 },
{ x0, y3, x3 - 1, y4 - 1, 1 },
{ x3, y3, x4 - 1, y4 - 1, 2 },
{ x4, y3, x7 - 1, y4 - 1, 2 },
{ x0, y4, x7 - 1, y7 - 1, 4 }
};
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground));
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent);
osd->DrawRectangle(x6, y0, x7 - 1, yt - 1, clrTransparent);
osd->DrawRectangle(x6, yb, x7 - 1, y7 - 1, clrTransparent);
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 2);
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
osd->DrawRectangle(x0, y1, x1 - 1, y6 - 1, frameColor);
osd->DrawEllipse (x1, y1, x2 - 1, y2 - 1, frameColor, -2);
osd->DrawEllipse (x1, y5, x2 - 1, y6 - 1, frameColor, -3);
osd->DrawEllipse (x0, y6, x1 - 1, y7 - 1, frameColor, 3);
osd->DrawRectangle(x1, y6, x2 - 1, y7 - 1, frameColor);
osd->DrawRectangle(x3, y6, x4 - 1, y7 - 1, frameColor);
osd->DrawRectangle(x5, y6, x6 - 1, y7 - 1, frameColor);
osd->DrawEllipse (x6, y6, x7 - 1, y7 - 1, frameColor, 5);
osd->DrawText(x3 + 5, y0, Title, Theme.Color(clrMenuTitle), frameColor, font, x4 - x3 - 5);
for (int i = 0; i < NumTracks; i++)
SetItem(Tracks[i], i, false);
}
cSkinSTTNGDisplayTracks::~cSkinSTTNGDisplayTracks()
{
delete osd;
}
void cSkinSTTNGDisplayTracks::SetItem(const char *Text, int Index, bool Current)
{
int y = y3 + Roundness + Index * lineHeight;
tColor ColorFg, ColorBg;
if (Current) {
ColorFg = Theme.Color(clrMenuItemCurrentFg);
ColorBg = Theme.Color(clrMenuItemCurrentBg);
osd->DrawEllipse (x1, y - Roundness, x2 - 1, y - 1, frameColor, -3);
osd->DrawRectangle(x1, y, x2 - 1, y + lineHeight - 1, frameColor);
osd->DrawEllipse (x1, y + lineHeight, x2 - 1, y + lineHeight + Roundness - 1, frameColor, -2);
osd->DrawRectangle(x3, y, x4 - 1, y + lineHeight - 1, ColorBg);
currentIndex = Index;
}
else {
ColorFg = Theme.Color(clrMenuItemSelectable);
ColorBg = Theme.Color(clrBackground);
if (currentIndex == Index) {
osd->DrawRectangle(x1, y - Roundness, x2 - 1, y + lineHeight + Roundness - 1, Theme.Color(clrBackground));
osd->DrawRectangle(x3, y, x4 - 1, y + lineHeight - 1, Theme.Color(clrBackground));
}
}
const cFont *font = cFont::GetFont(fontOsd);
int xt = x3 + 5;
osd->DrawText(xt, y, Text, ColorFg, ColorBg, font, x4 - xt);
}
void cSkinSTTNGDisplayTracks::SetTrack(int Index, const char * const *Tracks)
{
if (currentIndex >= 0)
SetItem(Tracks[currentIndex], currentIndex, false);
SetItem(Tracks[Index], Index, true);
}
void cSkinSTTNGDisplayTracks::Flush(void)
{
osd->Flush();
}
// --- cSkinSTTNGDisplayMessage ---------------------------------------------- // --- cSkinSTTNGDisplayMessage ----------------------------------------------
class cSkinSTTNGDisplayMessage : public cSkinDisplayMessage { class cSkinSTTNGDisplayMessage : public cSkinDisplayMessage {
@ -909,6 +1043,11 @@ cSkinDisplayVolume *cSkinSTTNG::DisplayVolume(void)
return new cSkinSTTNGDisplayVolume; return new cSkinSTTNGDisplayVolume;
} }
cSkinDisplayTracks *cSkinSTTNG::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
return new cSkinSTTNGDisplayTracks(Title, NumTracks, Tracks);
}
cSkinDisplayMessage *cSkinSTTNG::DisplayMessage(void) cSkinDisplayMessage *cSkinSTTNG::DisplayMessage(void)
{ {
return new cSkinSTTNGDisplayMessage; return new cSkinSTTNGDisplayMessage;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skinsttng.h 1.1 2004/04/18 09:38:47 kls Exp $ * $Id: skinsttng.h 1.2 2005/01/02 14:39:29 kls Exp $
*/ */
#ifndef __SKINSTTNG_H #ifndef __SKINSTTNG_H
@ -20,6 +20,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void); virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly); virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void); virtual cSkinDisplayVolume *DisplayVolume(void);
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual cSkinDisplayMessage *DisplayMessage(void); virtual cSkinDisplayMessage *DisplayMessage(void);
}; };

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: status.c 1.5 2003/05/03 14:47:44 kls Exp $ * $Id: status.c 1.6 2005/01/02 12:09:12 kls Exp $
*/ */
#include "status.h" #include "status.h"
@ -47,6 +47,12 @@ void cStatus::MsgSetVolume(int Volume, bool Absolute)
sm->SetVolume(Volume, Absolute); sm->SetVolume(Volume, Absolute);
} }
void cStatus::MsgSetAudioTrack(int Index, const char * const *Tracks)
{
for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm))
sm->SetAudioTrack(Index, Tracks);
}
void cStatus::MsgOsdClear(void) void cStatus::MsgOsdClear(void)
{ {
for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm))

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: status.h 1.6 2003/05/03 14:43:18 kls Exp $ * $Id: status.h 1.7 2005/01/02 12:08:12 kls Exp $
*/ */
#ifndef __STATUS_H #ifndef __STATUS_H
@ -36,6 +36,9 @@ protected:
virtual void SetVolume(int Volume, bool Absolute) {} virtual void SetVolume(int Volume, bool Absolute) {}
// The volume has been set to the given value, either // The volume has been set to the given value, either
// absolutely or relative to the current volume. // absolutely or relative to the current volume.
virtual void SetAudioTrack(int Index, const char * const *Tracks) {}
// The audio track has been set to the one given by Index, which
// points into the Tracks array of strings.
virtual void OsdClear(void) {} virtual void OsdClear(void) {}
// The OSD has been cleared. // The OSD has been cleared.
virtual void OsdTitle(const char *Title) {} virtual void OsdTitle(const char *Title) {}
@ -67,6 +70,7 @@ public:
static void MsgRecording(const cDevice *Device, const char *Name); static void MsgRecording(const cDevice *Device, const char *Name);
static void MsgReplaying(const cControl *Control, const char *Name); static void MsgReplaying(const cControl *Control, const char *Name);
static void MsgSetVolume(int Volume, bool Absolute); static void MsgSetVolume(int Volume, bool Absolute);
static void MsgSetAudioTrack(int Index, const char * const *Tracks);
static void MsgOsdClear(void); static void MsgOsdClear(void);
static void MsgOsdTitle(const char *Title); static void MsgOsdTitle(const char *Title);
static void MsgOsdStatusMessage(const char *Message); static void MsgOsdStatusMessage(const char *Message);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: transfer.c 1.19 2004/11/28 11:51:00 kls Exp $ * $Id: transfer.c 1.20 2004/12/27 11:08:34 kls Exp $
*/ */
#include "transfer.h" #include "transfer.h"
@ -58,11 +58,7 @@ void cTransfer::Action(void)
int PollTimeouts = 0; int PollTimeouts = 0;
uchar *p = NULL; uchar *p = NULL;
int Result = 0; int Result = 0;
// XXX Apparently this isn't necessary with the new PES data handling that #define FW_NEEDS_BUFFER_RESERVE_FOR_AC3
// XXX was intorduced in VDR 1.3.18. If you do need this, enable the following
// XXX line and send an email to kls@cadsoft.de. If nobody requires this, it
// XXX will be removed later. kls 2004-12-27
//#define FW_NEEDS_BUFFER_RESERVE_FOR_AC3
#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3 #ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3
bool Cleared = false; bool Cleared = false;
bool GotBufferReserve = false; bool GotBufferReserve = false;

11
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.5 1.30 2004/12/18 12:40:47 kls Exp $ .\" $Id: vdr.5 1.31 2005/01/02 13:57:10 kls Exp $
.\" .\"
.TH vdr 5 "19 Dec 2004" "1.3.18" "Video Disk Recorder Files" .TH vdr 5 "19 Dec 2004" "1.3.18" "Video Disk Recorder Files"
.SH NAME .SH NAME
@ -613,6 +613,7 @@ l l.
\fBT\fR@<title> \fBT\fR@<title>
\fBS\fR@<short text> \fBS\fR@<short text>
\fBD\fR@<description> \fBD\fR@<description>
\fBX\fR@<stream> <type> <language> <descr>
\fBV\fR@<vps time> \fBV\fR@<vps time>
\fBe\fR@ \fBe\fR@
\fBc\fR@ \fBc\fR@
@ -622,8 +623,10 @@ Lowercase characters mark the end of a sequence that was started by the
corresponding uppercase character. The outer frame consists of a sequence corresponding uppercase character. The outer frame consists of a sequence
of one or more \fBC\fR...\fBc\fR (Channel) entries. Inside these any number of of one or more \fBC\fR...\fBc\fR (Channel) entries. Inside these any number of
\fBE\fR...\fBe\fR (Event) entries are allowed. \fBE\fR...\fBe\fR (Event) entries are allowed.
The \fBT\fR, \fBS\fR and \fBD\fR entries are optional (although every event All other tags are optional (although every event
should at least have a \fBT\fR entry). should at least have a \fBT\fR entry).
There may be several \fBX\fR tags, depending on the number of tracks (video, audio etc.)
the event provides.
.TS .TS
tab (@); tab (@);
@ -636,6 +639,10 @@ l l.
<title> @is the title of the event <title> @is the title of the event
<short text> @is the short text of the event (typically the name of the episode etc.) <short text> @is the short text of the event (typically the name of the episode etc.)
<description> @is the description of the event (any '|' characters will be interpreted as newlines) <description> @is the description of the event (any '|' characters will be interpreted as newlines)
<stream> @is the stream content (1 = video, 2 = audio)
<type> @is the stream type according to ETSI EN 300 468
<language> @is the three letter language code
<descr> @is the description of this stream component
<vps time> @is the Video Programming Service time of this event <vps time> @is the Video Programming Service time of this event
.TE .TE

12
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/vdr * The project's page is at http://www.cadsoft.de/vdr
* *
* $Id: vdr.c 1.196 2004/12/26 10:30:30 kls Exp $ * $Id: vdr.c 1.197 2005/01/02 14:39:41 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -678,7 +678,7 @@ int main(int argc, char *argv[])
case kChanDn: case kChanDn:
cDevice::SwitchChannel(NORMALKEY(key) == kChanUp ? 1 : -1); cDevice::SwitchChannel(NORMALKEY(key) == kChanUp ? 1 : -1);
break; break;
// Volume Control: // Volume control:
case kVolUp|k_Repeat: case kVolUp|k_Repeat:
case kVolUp: case kVolUp:
case kVolDn|k_Repeat: case kVolDn|k_Repeat:
@ -697,6 +697,14 @@ int main(int argc, char *argv[])
cDisplayVolume::Process(key); cDisplayVolume::Process(key);
key = kNone; // nobody else needs to see these keys key = kNone; // nobody else needs to see these keys
break; break;
// Audio track control:
case kAudio:
if (!Menu && !cOsd::IsOpen())
Menu = Temp = cDisplayTracks::Create();
else
cDisplayTracks::Process(key);
key = kNone;
break;
// Pausing live video: // Pausing live video:
case kPause: case kPause:
if (!cControl::Control()) { if (!cControl::Control()) {