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

383 lines
17 KiB
C++

/*
* device.h: The basic device interface
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.h 1.23 2002/10/12 11:15:13 kls Exp $
*/
#ifndef __DEVICE_H
#define __DEVICE_H
#include "thread.h"
#include "tools.h"
#define MAXDEVICES 16 // the maximum number of devices in the system
#define MAXCACAPS 16 // the maximum number of different CA values per device
#define MAXPIDHANDLES 16 // the maximum number of different PIDs per device
#define MAXRECEIVERS 16 // the maximum number of receivers per device
#define MAXVOLUME 255
#define VOLUMEDELTA 5 // used to increase/decrease the volume
#define TS_SIZE 188
#define TS_SYNC_BYTE 0x47
#define PID_MASK_HI 0x1F
enum eSetChannelResult { scrOk, scrNotAvailable, scrNoTransfer, scrFailed };
enum ePlayMode { pmNone, // audio/video from decoder
pmAudioVideo, // audio/video from player
pmAudioOnly, // audio only from player, video from decoder
pmAudioOnlyBlack, // audio only from player, no video (black screen)
pmExtern_THIS_SHOULD_BE_AVOIDED
// external player (e.g. MPlayer), release the device
// WARNING: USE THIS MODE ONLY AS A LAST RESORT, IF YOU
// ABSOLUTELY, POSITIVELY CAN'T IMPLEMENT YOUR PLAYER
// THE WAY IT IS SUPPOSED TO WORK. FORCING THE DEVICE
// TO RELEASE ITS FILES HANDLES (OR WHATEVER RESOURCES
// IT MAY USE) TO ALLOW AN EXTERNAL PLAYER TO ACCESS
// THEM MEANS THAT SUCH A PLAYER WILL NEED TO HAVE
// DETAILED KNOWLEDGE ABOUT THE INTERNALS OF THE DEVICE
// IN USE. AS A CONSEQUENCE, YOUR PLAYER MAY NOT WORK
// IF A PARTICULAR VDR INSTALLATION USES A DEVICE NOT
// KNOWN TO YOUR PLAYER.
};
class cOsdBase;
class cChannel;
class cPlayer;
class cReceiver;
class cSpuDecoder;
class cDevice : public cThread {
private:
static int numDevices;
static int useDevice;
static cDevice *device[MAXDEVICES];
static cDevice *primaryDevice;
public:
static int NumDevices(void) { return numDevices; }
// Returns the total number of devices.
static void SetUseDevice(int n);
// Sets the 'useDevice' flag of the given device.
// If this function is not called before initializing, all devices
// will be used.
static bool UseDevice(int n) { return useDevice == 0 || (useDevice & (1 << n)) != 0; }
// Tells whether the device with the given card index shall be used in
// this instance of VDR.
static bool SetPrimaryDevice(int n);
// Sets the primary device to 'n' (which must be in the range
// 1...numDevices) and returns true if this was possible.
static cDevice *PrimaryDevice(void) { return primaryDevice; }
// Returns the primary device.
static cDevice *GetDevice(int Index);
// Returns the device with the Index (if Index is in the range
// 0..numDevices-1, NULL otherwise).
static cDevice *GetDevice(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
// Returns a device that is able to receive the given Channel at the
// given Priority (see ProvidesChannel() for more information on how
// priorities are handled, and the meaning of NeedsDetachReceivers).
static void SetCaCaps(int Index = -1);
// Sets the CaCaps of the given device according to the Setup data.
// By default the CaCaps of all devices are set.
static void Shutdown(void);
// Closes down all devices.
// Must be called at the end of the program.
private:
static int nextCardIndex;
int cardIndex;
int caCaps[MAXCACAPS];
protected:
cDevice(void);
virtual ~cDevice();
static int NextCardIndex(int n = 0);
// Each device in a given machine must have a unique card index, which
// will be used to identify the device for assigning Ca parameters and
// deciding whether to actually use that device in this particular
// instance of VDR. Every time a new cDevice is created, it will be
// given the current nextCardIndex, and then nextCardIndex will be
// automatically incremented by 1. A derived class can determine whether
// a given device shall be used by checking UseDevice(NextCardIndex()).
// If a device is skipped, or if there are possible device indexes left
// after a derived class has set up all its devices, NextCardIndex(n)
// must be called, where n is the number of card indexes to skip.
virtual void MakePrimaryDevice(bool On);
// Informs a device that it will be the primary device. If there is
// anything the device needs to set up when it becomes the primary
// device (On = true) or to shut down when it no longer is the primary
// device (On = false), it should do so in this function.
public:
bool IsPrimaryDevice(void) const { return this == primaryDevice; }
int CardIndex(void) const { return cardIndex; }
// Returns the card index of this device (0 ... MAXDEVICES - 1).
int DeviceNumber(void) const;
// Returns number of this device (0 ... MAXDEVICES - 1).
int ProvidesCa(int Ca) const;
// Checks whether this device provides the given value in its
// caCaps. Returns 0 if the value is not provided, 1 if only this
// value is provided, and > 1 if this and other values are provided.
// If the given value is equal to the number of this device,
// 1 is returned. If it is 0 (FTA), 1 plus the number of other values
// in caCaps is returned.
virtual bool HasDecoder(void) const;
// Tells whether this device has an MPEG decoder.
// OSD facilities
public:
virtual cOsdBase *NewOsd(int x, int y);
// Creates a new cOsdBase object that can be used by the cOsd class
// to display information on the screen, with the upper left corner
// of the OSD at the given coordinates. If a derived cDevice doesn't
// implement this function, NULL will be returned by default (which
// means the device has no OSD capabilities).
virtual cSpuDecoder *GetSpuDecoder(void);
// Returns a pointer to the device's SPU decoder (or NULL, if this
// device doesn't have an SPU decoder).
// Channel facilities
protected:
static int currentChannel;
public:
virtual bool ProvidesSource(int Source) const;
// Returns true if this device can provide the given source.
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
// Returns true if this device can provide the given channel.
// In case the device has cReceivers attached to it or it is the primary
// device, Priority is used to decide whether the caller's request can
// be honored.
// The special Priority value -1 will tell the caller whether this device
// is principally able to provide the given Channel, regardless of any
// attached cReceivers.
// If NeedsDetachReceivers is given, the resulting value in it will tell the
// caller whether or not it will have to detach any currently attached
// receivers from this device before calling SwitchChannel. Note
// that the return value in NeedsDetachReceivers is only meaningful if the
// function itself actually returns true.
// The default implementation always returns false, so a derived cDevice
// class that can provide channels must implement this function.
bool SwitchChannel(const cChannel *Channel, bool LiveView);
// Switches the device to the given Channel, initiating transfer mode
// if necessary.
static bool SwitchChannel(int Direction);
// Switches the primary device to the next available channel in the given
// Direction (only the sign of Direction is evaluated, positive values
// switch to higher channel numbers).
private:
eSetChannelResult SetChannel(const cChannel *Channel, bool LiveView);
// Sets the device to the given channel (general setup).
protected:
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
// Sets the device to the given channel (actual physical setup).
public:
static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
// Returns the number of the current channel on the primary device.
// PID handle facilities
private:
bool active;
virtual void Action(void);
protected:
enum ePidType { ptAudio, ptVideo, ptTeletext, ptDolby, ptOther };
class cPidHandle {
public:
int pid;
int handle;
int used;
cPidHandle(void) { pid = used = 0; handle = -1; }
};
cPidHandle pidHandles[MAXPIDHANDLES];
bool HasPid(int Pid) const;
// Returns true if this device is currently receiving the given PID.
bool AddPid(int Pid, ePidType PidType = ptOther);
// Adds a PID to the set of PIDs this device shall receive.
void DelPid(int Pid);
// Deletes a PID from the set of PIDs this device shall receive.
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
// Does the actual PID setting on this device.
// On indicates whether the PID shall be added or deleted.
// Handle->handle can be used by the device to store information it
// needs to receive this PID (for instance a file handle).
// Handle->used indicated how many receivers are using this PID.
// Type indicates some special types of PIDs, which the device may
// need to set in a specific way.
// Image Grab facilities
public:
virtual bool GrabImage(const char *FileName, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1);
// Grabs the currently visible screen image into the given file, with the
// given parameters.
// Video format facilities
public:
virtual void SetVideoFormat(bool VideoFormat16_9);
// Sets the output video format to either 16:9 or 4:3 (only useful
// if this device has an MPEG decoder).
// Audio facilities
private:
bool mute;
int volume;
protected:
virtual void SetVolumeDevice(int Volume);
// Sets the audio volume on this device (Volume = 0...255).
virtual int NumAudioTracksDevice(void) const;
// Returns the number of audio tracks that are currently available on this
// device. The default return value is 0, meaning that this device
// doesn't have multiple audio track capabilities. The return value may
// change with every call and need not necessarily be the number of list
// entries returned by GetAudioTracksDevice(). This function is mainly called to
// decide whether there should be an "Audio" button in a menu.
virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const;
// Returns a list of currently available audio tracks. The last entry in the
// list must be NULL. The number of entries does not necessarily have to be
// the same as returned by a previous call to NumAudioTracksDevice().
// If CurrentTrack is given, it will be set to the index of the current track
// in the returned list. Note that the list must not be changed after it has
// been returned by a call to GetAudioTracksDevice()! The only time the list may
// change is *inside* the GetAudioTracksDevice() function.
// By default the return value is NULL and CurrentTrack, if given, will not
// have any meaning.
virtual void SetAudioTrackDevice(int Index);
// Sets the current audio track to the given value, which should be within the
// range of the list returned by a previous call to GetAudioTracksDevice()
// (otherwise nothing will happen).
public:
bool IsMute(void) const { return mute; }
bool ToggleMute(void);
// Turns the volume off or on and returns the new mute state.
void SetVolume(int Volume, bool Absolute = false);
// Sets the volume to the given value, either absolutely or relative to
// the current volume.
static int CurrentVolume(void) { return primaryDevice ? primaryDevice->volume : 0; }//XXX???
int NumAudioTracks(void) const;
// Returns the number of audio tracks that are currently available on this
// device or a player attached to it.
const char **GetAudioTracks(int *CurrentTrack = NULL) const;
// Returns a list of currently available audio tracks. The last entry in the
// list is NULL. The number of entries does not necessarily have to be
// the same as returned by a previous call to NumAudioTracks().
// If CurrentTrack is given, it will be set to the index of the current track
// in the returned list.
// By default the return value is NULL and CurrentTrack, if given, will not
// have any meaning.
void SetAudioTrack(int Index);
// Sets the current audio track to the given value, which should be within the
// range of the list returned by a previous call to GetAudioTracks() (otherwise
// nothing will happen).
// Player facilities
private:
cPlayer *player;
bool playerDetached;
protected:
virtual bool SetPlayMode(ePlayMode PlayMode);
// Sets the device into the given play mode.
// Returns true if the operation was successful.
public:
virtual void TrickSpeed(int Speed);
// Sets the device into a mode where replay is done slower.
// Every single frame shall then be displayed the given number of
// times.
virtual void Clear(void);
// Clears all video and audio data from the device.
virtual void Play(void);
// Sets the device into play mode (after a previous trick
// mode).
virtual void Freeze(void);
// Puts the device into "freeze frame" mode.
virtual void Mute(void);
// Turns off audio while replaying.
virtual void StillPicture(const uchar *Data, int Length);
// Displays the given I-frame as a still picture.
virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
// Returns true if the device itself or any of the file handles in
// Poller is ready for further action.
// If TimeoutMs is not zero, the device will wait up to the given number
// of milleseconds before returning in case there is no immediate
// need for data.
virtual int PlayVideo(const uchar *Data, int Length);
// Actually plays the given data block as video. The data must be
// part of a PES (Packetized Elementary Stream) which can contain
// one video and one audio strem.
virtual int PlayAudio(const uchar *Data, int Length);
// Plays additional audio streams, like Dolby Digital.
bool Replaying(void) const;
// Returns true if we are currently replaying.
void StopReplay(void);
// Stops the current replay session (if any).
bool AttachPlayer(cPlayer *Player);
// Attaches the given player to this device.
void Detach(cPlayer *Player);
// Detaches the given player from this device.
bool PlayerDetached(void);
// Returns true if a player has been detached and resets the 'playerDetached' flag.
// Receiver facilities
private:
cReceiver *receiver[MAXRECEIVERS];
int ca;
int CanShift(int Ca, int Priority, int UsedCards = 0) const;
protected:
int Priority(void) const;
// Returns the priority of the current receiving session (0..MAXPRIORITY),
// or -1 if no receiver is currently active. The primary device will
// always return at least Setup.PrimaryLimit-1.
virtual bool OpenDvr(void);
// Opens the DVR of this device and prepares it to deliver a Transport
// Stream for use in a cReceiver.
virtual void CloseDvr(void);
// Shuts down the DVR.
virtual bool GetTSPacket(uchar *&Data);
// Gets exactly one TS packet from the DVR of this device and returns
// a pointer to it in Data. Only the first 188 bytes (TS_SIZE) Data
// points to are valid and may be accessed. If there is currently no
// new data available, Data will be set to NULL. The function returns
// false in case of a non recoverable error, otherwise it returns true,
// even if Data is NULL.
public:
int Ca(void) const { return ca; }
// Returns the ca of the current receiving session.
bool Receiving(void) const;
// Returns true if we are currently receiving.
bool AttachReceiver(cReceiver *Receiver);
// Attaches the given receiver to this device.
void Detach(cReceiver *Receiver);
// Detaches the given receiver from this device.
};
// Derived cDevice classes that can receive channels will have to provide
// Transport Stream (TS) packets one at a time. cTSBuffer implements a
// simple buffer that allows the device to read a larger amount of data
// from the driver with each call to Read(), thus avoiding the overhead
// of getting each TS packet separately from the driver. It also makes
// sure the returned data points to a TS packet and automatically
// re-synchronizes after broken packet.
class cTSBuffer {
private:
int f;
int size;
int cardIndex;
int tsRead;
int tsWrite;
uchar *buf;
bool firstRead;
int Used(void) { return tsRead <= tsWrite ? tsWrite - tsRead : size - tsRead + tsWrite; }
public:
cTSBuffer(int File, int Size, int CardIndex);
~cTSBuffer();
int Read(void);
uchar *Get(void);
};
#endif //__DEVICE_H