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.
- 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
for reporting this one).
@ -3251,3 +3251,17 @@ Video Disk Recorder Revision History
Zocholl for pointing out this problem).
- Added cDevice::mutexReceiver to avoid a race condition when attaching/detaching
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
Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu
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
Blue - Stop/Resume Mark On/Off(1) - Summary Stop
0..9 Ch select - Sort(3) Day(4) Numeric inp. Exec cmd(2) Editing
@ -49,6 +49,8 @@ Version 1.2
Volume- volume down
Mute mute
Audio select audio track
Schedule \
Channels |
Timers | directly access the VDR
@ -187,15 +189,16 @@ Version 1.2
To bring up the channel display without switching channels you can press
the "Ok" button.
* Selecting language specific audio track
* Selecting audio tracks
If the current channel provides different audio tracks (typically for
different languages), the "Green" button in the "VDR" menu can be pressed
to toggle between these. There can be two different audio PIDs per channel,
assuming that typically a channel broadcasts a country specific language
plus the movie's original soundtrack.
Recordings made form such channels will contain both audio tracks, and when
replaying the desired audio track can be selected the same way.
If the current channel or recording provides different audio tracks (for
different languages or Dolby Digital), the "Green" button in the "VDR" menu can
be pressed to bring up the "Audio" menu. Within this menu, the "Up" and "Down"
keys can be used to switch between the audio tracks. If your remote control has
a dedicated "Audio" button, the first press of that button brings up the "Audio"
menu, and every further press switches to the next available audio track.
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
@ -495,14 +498,15 @@ Version 1.2
A value of '0' completely turns off scanning on both single
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:
0 = no EPG fixing
1 = basic fixing of text location (Title, Episode and
Extended Description)
2 = removal of excess whitespace and hyphens, mapping of
wrongly used characters
Default is '2'.
3 = fix stream component descriptions
Default is '3'.
Note that after changing the setting of this parameter
any EPG data that has already been received will remain
in its existing format - only newly received data will

View File

@ -1362,6 +1362,9 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
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);
};
</pre></td></tr></table><p>

View File

@ -9,6 +9,7 @@ VDR Plugin 'skincurses' Revision History
- Fixed some default parameters.
2004-12-26: Version 0.0.3
2005-01-02: Version 0.0.3
- 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.
*
* $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>
@ -558,6 +558,68 @@ void cSkinCursesDisplayVolume::Flush(void)
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 ---------------------------------------------
class cSkinCursesDisplayMessage : public cSkinDisplayMessage {
@ -600,6 +662,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void);
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual cSkinDisplayMessage *DisplayMessage(void);
};
@ -633,6 +696,11 @@ cSkinDisplayVolume *cSkinCurses::DisplayVolume(void)
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)
{
return new cSkinCursesDisplayMessage;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@ -604,15 +604,19 @@ void cDevice::ClrAvailableTracks(void)
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);
if ((Type == ttAudio && IS_AUDIO_TRACK(t)) ||
(Type == ttDolby && IS_DOLBY_TRACK(t))) {
if (Language)
strn0cpy(availableTracks[t].language, Language, sizeof(availableTracks[t].language));
availableTracks[t].flags = Flags;
availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking
if (Description)
strn0cpy(availableTracks[t].description, Description, sizeof(availableTracks[t].description));
if (Id) {
availableTracks[t].flags = Flags;
availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking
}
return true;
}
else
@ -652,21 +656,6 @@ bool cDevice::SetCurrentAudioTrack(eTrackType Type)
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
{
return HasDecoder();

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@ -75,8 +75,9 @@ enum eTrackType { ttNone,
#define IS_DOLBY_TRACK(t) (ttDolbyFirst <= (t) && (t) <= ttDolbyLast)
struct tTrackId {
uint16_t id; // The PES packet id or the PID.
char language[8]; // something like either "eng" or "deu/eng"
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.
};
@ -319,10 +320,12 @@ protected:
///< Sets the current audio track to the given value.
public:
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.
///< 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
///< given Language and Description will be set.
///< \return Returns true if the track was set correctly, false otherwise.
const tTrackId *GetTrack(eTrackType Type);
///< Returns a pointer to the given track id, or NULL if Type is not
@ -335,10 +338,6 @@ 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.
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

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@ -860,10 +860,8 @@ void cDvbDevice::SetAudioTrackDevice(eTrackType Type)
else if (IS_DOLBY_TRACK(Type)) {
// Currently this works only in Transfer Mode
cChannel *Channel = Channels.GetByNumber(CurrentChannel());
if (Channel) {
SetChannelDevice(Channel, false);
cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid(0), Channel->Apid(1), Channel->Dpid(0), Channel->Dpid(1)));
}
if (Channel)
SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
}
}
}

32
eit.c
View File

@ -8,7 +8,7 @@
* 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>.
*
* $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"
@ -91,6 +91,8 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL;
SI::ShortEventDescriptor *ShortEventDescriptor = NULL;
cLinkChannels *LinkChannels = NULL;
int NumComponents = 0;
SI::ComponentDescriptor *ComponentDescriptors[MAXCOMPONENTS];
for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) {
switch (d->getDescriptorTag()) {
case SI::ExtendedEventDescriptorTag: {
@ -186,6 +188,20 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
}
}
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: ;
}
delete d;
@ -205,8 +221,20 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
delete ExtendedEventDescriptors;
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)
channel->SetLinkChannels(LinkChannels);
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
* 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"
@ -16,6 +16,66 @@
#include <ctype.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(tChannelID ChannelID, u_int16_t EventID)
@ -28,6 +88,7 @@ cEvent::cEvent(tChannelID ChannelID, u_int16_t EventID)
title = NULL;
shortText = NULL;
description = NULL;
components = NULL;
startTime = 0;
duration = 0;
vps = 0;
@ -39,6 +100,7 @@ cEvent::~cEvent()
free(title);
free(shortText);
free(description);
delete components;
}
int cEvent::Compare(const cListObject &ListObject) const
@ -85,6 +147,12 @@ void cEvent::SetDescription(const char *Description)
description = strcpyrealloc(description, Description);
}
void cEvent::SetComponents(cComponents *Components)
{
delete components;
components = Components;
}
void cEvent::SetStartTime(time_t StartTime)
{
startTime = StartTime;
@ -168,6 +236,12 @@ void cEvent::Dump(FILE *f, const char *Prefix) const
fprintf(f, "%sD %s\n", Prefix, description);
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)
fprintf(f, "%sV %ld\n", Prefix, vps);
fprintf(f, "%se\n", Prefix);
@ -178,6 +252,8 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
{
if (Schedule) {
cEvent *Event = NULL;
int NumComponents = 0;
char *ComponentStrings[MAXCOMPONENTS];
char *s;
cReadLine ReadLine;
while ((s = ReadLine.Read(f)) != NULL) {
@ -199,6 +275,7 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
Event->SetDuration(Duration);
}
}
NumComponents = 0;
}
break;
case 'T': if (Event)
@ -212,10 +289,26 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
Event->SetDescription(t);
}
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)
Event->SetVps(atoi(t));
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;
case 'c': // to keep things simple we react on 'c' here
return true;
@ -228,7 +321,7 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
return false;
}
#define MAXEPGBUGFIXSTATS 8
#define MAXEPGBUGFIXSTATS 12
#define MAXEPGBUGFIXCHANS 100
struct tEpgBugFixStats {
int hits;
@ -476,6 +569,72 @@ void cEvent::FixEpgBugs(void)
strreplace(title, '`', '\'');
strreplace(shortText, '`', '\'');
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;
}
}
}
}
}

54
epg.h
View File

@ -7,7 +7,7 @@
* Original version (as used in VDR before 1.3.0) written by
* 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
@ -17,26 +17,50 @@
#include "thread.h"
#include "tools.h"
#define MAXEPGBUGFIXLEVEL 2
#define MAXEPGBUGFIXLEVEL 3
#define MAXCOMPONENTS 32
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 cEvent : public cListObject {
private:
tChannelID channelID; // Channel ID of program for this event
u_int16_t eventID; // Event ID of this event
uchar tableID; // Table ID this event came from
uchar version; // Version number of section this event came from
int runningStatus; // 0=undefined, 1=not running, 2=starts in a few seconds, 3=pausing, 4=running
char *title; // Title of this event
char *shortText; // Short description of this event (typically the episode name in case of a series)
char *description; // Description of this event
time_t startTime; // Start time of this event
int duration; // Duration of this event in seconds
time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL)
time_t seen; // When this event was last seen in the data stream
tChannelID channelID; // Channel ID of program for this event
u_int16_t eventID; // Event ID of this event
uchar tableID; // Table ID this event came from
uchar version; // Version number of section this event came from
int runningStatus; // 0=undefined, 1=not running, 2=starts in a few seconds, 3=pausing, 4=running
char *title; // Title of this event
char *shortText; // Short description of this event (typically the episode name in case of a series)
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
int duration; // Duration of this event in seconds
time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL)
time_t seen; // When this event was last seen in the data stream
public:
cEvent(tChannelID ChannelID, u_int16_t EventID);
~cEvent();
@ -49,6 +73,7 @@ public:
const char *Title(void) const { return title; }
const char *ShortText(void) const { return shortText; }
const char *Description(void) const { return description; }
const cComponents *Components(void) const { return components; }
time_t StartTime(void) const { return startTime; }
time_t EndTime(void) const { return startTime + duration; }
int Duration(void) const { return duration; }
@ -67,6 +92,7 @@ public:
void SetTitle(const char *Title);
void SetShortText(const char *ShortText);
void SetDescription(const char *Description);
void SetComponents(cComponents *Components); // Will take ownership of Components!
void SetStartTime(time_t StartTime);
void SetDuration(int Duration);
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
* 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:
*
@ -4610,6 +4610,27 @@ const tI18nPhrase Phrases[] = {
"Hääletu",
"Sluk lyd",
},
{ "Audio",
"Audio",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
// Miscellaneous:
{ "yes",
"ja",

3
keys.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@ -44,6 +44,7 @@ static tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
{ kVolUp, "Volume+" },
{ kVolDn, "Volume-" },
{ kMute, "Mute" },
{ kAudio, "Audio" },
{ kSchedule, "Schedule" },
{ kChannels, "Channels" },
{ kTimers, "Timers" },

3
keys.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@ -38,6 +38,7 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
kVolUp,
kVolDn,
kMute,
kAudio,
kSchedule,
kChannels,
kTimers,

126
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@ -2410,7 +2410,7 @@ void cMenuMain::Set(const char *Plugin)
// 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();
lastActivity = time(NULL);
}
@ -2471,8 +2471,10 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
state = replaying ? osContinue : osRecord;
break;
case kGreen: if (!HadSubMenu) {
cDevice::PrimaryDevice()->IncCurrentAudioTrack();
state = osEnd;
if (cDevice::PrimaryDevice()->NumAudioTracks() > 1) {
cRemote::Put(kAudio, true);
state = osEnd;
}
}
break;
case kYellow: if (!HadSubMenu)
@ -2764,6 +2766,122 @@ eOSState cDisplayVolume::ProcessKey(eKeys Key)
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(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
* 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
@ -75,6 +75,23 @@ public:
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 {
private:
cCiMenu *ciMenu;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@ -19,7 +19,7 @@ private:
cDevice *device;
ePlayMode playMode;
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 DeviceFlush(int TimeoutMs = 0) { return device ? device->Flush(TimeoutMs) : true; }
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
* 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"
@ -502,6 +502,84 @@ void cSkinClassicDisplayVolume::Flush(void)
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 --------------------------------------------
class cSkinClassicDisplayMessage : public cSkinDisplayMessage {
@ -571,6 +649,12 @@ cSkinDisplayVolume *cSkinClassic::DisplayVolume(void)
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)
{
return new cSkinClassicDisplayMessage;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@ -20,6 +20,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void);
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual cSkinDisplayMessage *DisplayMessage(void);
};

18
skins.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@ -66,8 +66,6 @@ public:
Red = Video options
Green = Info now
Yellow = Info next
Blue = Audio options
AudioOptions
VideoOptions
*/
};
@ -223,6 +221,14 @@ public:
///< 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 {
///< This class implements a simple message display.
public:
@ -275,6 +281,12 @@ public:
virtual cSkinDisplayVolume *DisplayVolume(void) = 0;
///< Creates and returns a new object for displaying the current volume.
///< 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;
///< Creates and returns a new object for displaying a message.
///< 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
* 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
@ -822,6 +822,140 @@ void cSkinSTTNGDisplayVolume::Flush(void)
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 ----------------------------------------------
class cSkinSTTNGDisplayMessage : public cSkinDisplayMessage {
@ -909,6 +1043,11 @@ cSkinDisplayVolume *cSkinSTTNG::DisplayVolume(void)
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)
{
return new cSkinSTTNGDisplayMessage;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@ -20,6 +20,7 @@ public:
virtual cSkinDisplayMenu *DisplayMenu(void);
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
virtual cSkinDisplayVolume *DisplayVolume(void);
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual cSkinDisplayMessage *DisplayMessage(void);
};

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@ -47,6 +47,12 @@ void cStatus::MsgSetVolume(int Volume, bool 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)
{
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
* 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
@ -36,6 +36,9 @@ protected:
virtual void SetVolume(int Volume, bool Absolute) {}
// The volume has been set to the given value, either
// 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) {}
// The OSD has been cleared.
virtual void OsdTitle(const char *Title) {}
@ -67,6 +70,7 @@ public:
static void MsgRecording(const cDevice *Device, const char *Name);
static void MsgReplaying(const cControl *Control, const char *Name);
static void MsgSetVolume(int Volume, bool Absolute);
static void MsgSetAudioTrack(int Index, const char * const *Tracks);
static void MsgOsdClear(void);
static void MsgOsdTitle(const char *Title);
static void MsgOsdStatusMessage(const char *Message);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@ -58,11 +58,7 @@ void cTransfer::Action(void)
int PollTimeouts = 0;
uchar *p = NULL;
int Result = 0;
// XXX Apparently this isn't necessary with the new PES data handling that
// 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
#define FW_NEEDS_BUFFER_RESERVE_FOR_AC3
#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3
bool Cleared = false;
bool GotBufferReserve = false;

11
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the
.\" 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"
.SH NAME
@ -613,6 +613,7 @@ l l.
\fBT\fR@<title>
\fBS\fR@<short text>
\fBD\fR@<description>
\fBX\fR@<stream> <type> <language> <descr>
\fBV\fR@<vps time>
\fBe\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
of one or more \fBC\fR...\fBc\fR (Channel) entries. Inside these any number of
\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).
There may be several \fBX\fR tags, depending on the number of tracks (video, audio etc.)
the event provides.
.TS
tab (@);
@ -636,6 +639,10 @@ l l.
<title> @is the title of the event
<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)
<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
.TE

12
vdr.c
View File

@ -22,7 +22,7 @@
*
* 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>
@ -678,7 +678,7 @@ int main(int argc, char *argv[])
case kChanDn:
cDevice::SwitchChannel(NORMALKEY(key) == kChanUp ? 1 : -1);
break;
// Volume Control:
// Volume control:
case kVolUp|k_Repeat:
case kVolUp:
case kVolDn|k_Repeat:
@ -697,6 +697,14 @@ int main(int argc, char *argv[])
cDisplayVolume::Process(key);
key = kNone; // nobody else needs to see these keys
break;
// Audio track control:
case kAudio:
if (!Menu && !cOsd::IsOpen())
Menu = Temp = cDisplayTracks::Create();
else
cDisplayTracks::Process(key);
key = kNone;
break;
// Pausing live video:
case kPause:
if (!cControl::Control()) {