1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
|
/*
* 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.8 2002/08/15 11:09:21 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, scrNoTransfer, scrFailed };
enum ePlayMode { pmNone, // audio/video from decoder
pmAudioVideo, // audio/video from player
pmAudioOnly, // audio only from player, video from decoder
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 cChannel;
class cPlayer;
class cReceiver;
class cDevice : 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 Ca, int Priority, int Frequency = 0, int Vpid = 0, bool *ReUse = NULL);
// Selects a free device, avoiding the primaryDevice if possible.
// If Ca is not 0, the device with the given number will be returned
// in case Ca is <= MAXDEVICES, or the device that provides the given
// value in its caCaps.
// If there is a device that is already receiving and can be re-used to
// receive another data stream, that device will be returned.
// If all devices are currently receiving, the one receiving with the
// lowest priority (if any) that is lower than the given Priority
// will be returned.
// If ReUse is given, the caller will be informed whether the device can be re-used
// for a new recording. If ReUse returns 'true', the caller must NOT switch the channel
// (the device is already properly tuned). Otherwise the caller MUST switch the channel.
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).
virtual int ProvidesCa(int Ca);
//XXX TODO temporarily made this function virtual - until a general
//XXX mechanism has been implemented
// 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 CanBeReUsed(int Frequency, int Vpid);//XXX TODO make it more abstract
// Tells whether this device is already receiving and allows another
// receiver with the given settings to be attached to it.
virtual bool HasDecoder(void) const;
// Tells whether this device has an MPEG decoder.
// Channel facilities
protected:
int currentChannel;
public:
eSetChannelResult SetChannel(const cChannel *Channel);
// Sets the device to the given channel (general setup).
virtual bool SetChannelDevice(const cChannel *Channel);
// Sets the device to the given channel (actual physical setup).
static int CurrentChannel(void) { return primaryDevice ? primaryDevice->currentChannel : 0; }
// Returns the number of the current channel on the primary device.
int Channel(void) { return currentChannel; }
// Returns the number of the current channel on this device.
// PID handle facilities
private:
bool active;
virtual void Action(void);
protected:
enum ePidType { ptVideo, ptAudio, ptTeletext, ptDolby, ptOther };
class cPidHandle {
public:
int pid;
int handle;
int used;
cPidHandle(void) { pid = used = 0; handle = -1; }
};
cPidHandle pidHandles[MAXPIDHANDLES];
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).
// Volume facilities
private:
bool mute;
int volume;
protected:
virtual void SetVolumeDevice(int Volume);
// Sets the audio volume on this device (Volume = 0...255).
public:
bool IsMute(void) { 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???
// Player facilities
private:
cPlayer *player;
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 NeedsData(int Wait = 0);
// Returns true if the device needs further data for replaying.
// If Wait 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);
// 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.
// Receiver facilities
private:
cReceiver *receiver[MAXRECEIVERS];
int ca;
int Priority(void);
// 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.
int CanShift(int Ca, int Priority, int UsedCards = 0);
protected:
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 int GetTSPacket(uchar *Data);
// Gets exactly one TS packet from the DVR of this device and copies it
// into the given memory area (which is exactly 188 bytes in size).
// Returns the number of bytes copied into Data (which must be 188).
// If there is currently no TS packet available, 0 should be returned.
// In case of a non recoverable error, returns -1.
public:
int Ca(void) { return ca; }
// Returns the ca of the current receiving session.
bool Receiving(void);
// 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.
};
#endif //__DEVICE_H
|