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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
|
diff --git a/device.c b/device.c
index 681049b..aaee92f 100644
--- a/device.c
+++ b/device.c
@@ -72,12 +72,18 @@ cDevice *cDevice::device[MAXDEVICES] = { NULL };
cDevice *cDevice::primaryDevice = NULL;
cDevice *cDevice::avoidDevice = NULL;
cList<cDeviceHook> cDevice::deviceHooks;
+cDevice *cDevice::nextParentDevice = NULL;
-cDevice::cDevice(void)
+cDevice::cDevice(cDevice *ParentDevice)
:patPmtParser(true)
+,parentDevice(ParentDevice)
+,subDevice(NULL)
{
+ if (!ParentDevice)
+ parentDevice = nextParentDevice;
+ cDevice::nextParentDevice = NULL;
cardIndex = nextCardIndex++;
- dsyslog("new device number %d", CardIndex() + 1);
+ dsyslog("new %sdevice number %d", parentDevice ? "sub-" : "", CardIndex() + 1);
SetDescription("receiver on device %d", CardIndex() + 1);
@@ -108,10 +114,14 @@ cDevice::cDevice(void)
for (int i = 0; i < MAXRECEIVERS; i++)
receiver[i] = NULL;
- if (numDevices < MAXDEVICES)
- device[numDevices++] = this;
+ if (!parentDevice) {
+ if (numDevices < MAXDEVICES)
+ device[numDevices++] = this;
+ else
+ esyslog("ERROR: too many devices or \"dynamite\"-unpatched device creator!");
+ }
else
- esyslog("ERROR: too many devices!");
+ parentDevice->subDevice = this;
}
cDevice::~cDevice()
@@ -120,6 +130,8 @@ cDevice::~cDevice()
DetachAllReceivers();
delete liveSubtitle;
delete dvbSubtitleConverter;
+ if (parentDevice && (parentDevice->subDevice == this))
+ parentDevice->subDevice = NULL;
}
bool cDevice::WaitForAllDevicesReady(int Timeout)
@@ -158,6 +170,8 @@ int cDevice::NextCardIndex(int n)
int cDevice::DeviceNumber(void) const
{
+ if (parentDevice)
+ return parentDevice->DeviceNumber();
for (int i = 0; i < numDevices; i++) {
if (device[i] == this)
return i;
@@ -328,6 +342,10 @@ bool cDevice::HasCi(void)
void cDevice::SetCamSlot(cCamSlot *CamSlot)
{
+ if (parentDevice) {
+ parentDevice->SetCamSlot(CamSlot);
+ return;
+ }
camSlot = CamSlot;
}
@@ -531,6 +549,10 @@ bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
void cDevice::StartSectionHandler(void)
{
+ if (parentDevice) {
+ parentDevice->StartSectionHandler();
+ return;
+ }
if (!sectionHandler) {
sectionHandler = new cSectionHandler(this);
AttachFilter(eitFilter = new cEitFilter);
@@ -542,6 +564,10 @@ void cDevice::StartSectionHandler(void)
void cDevice::StopSectionHandler(void)
{
+ if (parentDevice) {
+ parentDevice->StopSectionHandler();
+ return;
+ }
if (sectionHandler) {
delete nitFilter;
delete sdtFilter;
@@ -568,12 +594,20 @@ void cDevice::CloseFilter(int Handle)
void cDevice::AttachFilter(cFilter *Filter)
{
+ if (parentDevice) {
+ parentDevice->AttachFilter(Filter);
+ return;
+ }
if (sectionHandler)
sectionHandler->Attach(Filter);
}
void cDevice::Detach(cFilter *Filter)
{
+ if (parentDevice) {
+ parentDevice->Detach(Filter);
+ return;
+ }
if (sectionHandler)
sectionHandler->Detach(Filter);
}
@@ -1690,3 +1724,25 @@ uchar *cTSBuffer::Get(void)
}
return NULL;
}
+
+// --- cDynamicDeviceProbe -------------------------------------------------------
+
+cList<cDynamicDeviceProbe> DynamicDeviceProbes;
+
+cList<cDynamicDeviceProbe::cDynamicDeviceProbeItem> cDynamicDeviceProbe::commandQueue;
+
+void cDynamicDeviceProbe::QueueDynamicDeviceCommand(eDynamicDeviceProbeCommand Cmd, const char *DevPath)
+{
+ if (DevPath)
+ commandQueue.Add(new cDynamicDeviceProbeItem(Cmd, new cString(DevPath)));
+}
+
+cDynamicDeviceProbe::cDynamicDeviceProbe(void)
+{
+ DynamicDeviceProbes.Add(this);
+}
+
+cDynamicDeviceProbe::~cDynamicDeviceProbe()
+{
+ DynamicDeviceProbes.Del(this, false);
+}
diff --git a/device.h b/device.h
index cb3bc2c..0b6634b 100644
--- a/device.h
+++ b/device.h
@@ -163,7 +163,6 @@ private:
static int nextCardIndex;
int cardIndex;
protected:
- cDevice(void);
virtual ~cDevice();
virtual bool Ready(void);
///< Returns true if this device is ready. Devices with conditional
@@ -191,8 +190,6 @@ protected:
///< base class.
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 the number of this device (0 ... numDevices).
virtual bool HasDecoder(void) const;
@@ -365,9 +362,6 @@ public:
///< Returns true if this device has a Common Interface.
void SetCamSlot(cCamSlot *CamSlot);
///< Sets the given CamSlot to be used with this device.
- cCamSlot *CamSlot(void) const { return camSlot; }
- ///< Returns the CAM slot that is currently used with this device,
- ///< or NULL if no CAM slot is in use.
// Image Grab facilities
@@ -524,9 +518,6 @@ private:
cTsToPes tsToPesSubtitle;
bool isPlayingVideo;
protected:
- const cPatPmtParser *PatPmtParser(void) const { return &patPmtParser; }
- ///< Returns a pointer to the patPmtParser, so that a derived device
- ///< can use the stream information from it.
virtual bool CanReplay(void) const;
///< Returns true if this device can currently start a replay session.
virtual bool SetPlayMode(ePlayMode PlayMode);
@@ -712,6 +703,30 @@ public:
///< Detaches all receivers from this device for this pid.
void DetachAllReceivers(void);
///< Detaches all receivers from this device.
+
+// --- dynamite subdevice patch start ---
+ friend class cDynamicDevice;
+private:
+ static cDevice *nextParentDevice;
+ ///< Holds the parent device for the next subdevice
+ ///< so the dynamite-plugin can work with unpatched plugins
+protected:
+ cDevice *parentDevice;
+ cDevice *subDevice;
+ cDevice(cDevice *ParentDevice = NULL);
+ const cPatPmtParser *PatPmtParser(void) const { if (parentDevice) return parentDevice->PatPmtParser(); return &patPmtParser; }
+ ///< Returns a pointer to the patPmtParser, so that a derived device
+ ///< can use the stream information from it.
+public:
+ int CardIndex(void) const { if (parentDevice) return parentDevice->cardIndex; return cardIndex; }
+ ///< Returns the card index of this device (0 ... MAXDEVICES - 1).
+ cCamSlot *CamSlot(void) const { if (parentDevice) return parentDevice->CamSlot(); return camSlot; }
+ ///< Returns the CAM slot that is currently used with this device,
+ ///< or NULL if no CAM slot is in use.
+ bool IsSubDevice(void) const { return (parentDevice != NULL); }
+ bool HasSubDevice(void) const { return (subDevice != NULL); }
+ cDevice *SubDevice(void) const { return subDevice; }
+ // --- dynamite subdevice patch end ---
};
/// Derived cDevice classes that can receive channels will have to provide
@@ -735,4 +750,47 @@ public:
uchar *Get(void);
};
+/// A plugin that want to create devices handled by the dynamite-plugin needs to create
+/// a cDynamicDeviceProbe derived object on the heap in order to have its Probe()
+/// function called, where it can actually create the appropriate device.
+/// The cDynamicDeviceProbe object must be created in the plugin's constructor,
+/// and deleted in its destructor.
+/// The "DevPath" hasn't to be a physical device or a path in the filesystem.
+/// It can be any string a plugin may react on.
+
+#define __DYNAMIC_DEVICE_PROBE
+
+enum eDynamicDeviceProbeCommand { ddpcAttach, ddpcDetach };
+
+class cDynamicDeviceProbe : public cListObject {
+ friend class cDynamicDevice;
+private:
+ class cDynamicDeviceProbeItem : public cListObject {
+ public:
+ eDynamicDeviceProbeCommand cmd;
+ cString *devpath;
+ cDynamicDeviceProbeItem(eDynamicDeviceProbeCommand Cmd, cString *DevPath):cmd(Cmd),devpath(DevPath) {}
+ virtual ~cDynamicDeviceProbeItem() { if (devpath) delete devpath; }
+ };
+ static cList<cDynamicDeviceProbeItem> commandQueue;
+ ///< A list where all attach/detach commands are queued
+ ///< so they can be processed in the MainThreadHook of
+ ///< the dynamite plugin.
+public:
+ static void QueueDynamicDeviceCommand(eDynamicDeviceProbeCommand Cmd, const char *DevPath);
+ ///< Plugins which support cDynamicDeviceProbe must use this function
+ ///< to queue the devices they normally create in their Initialize method.
+ ///< These devices are created as subdevices in the Start-method of the dynamite-plugin.
+ cDynamicDeviceProbe(void);
+ virtual ~cDynamicDeviceProbe();
+ virtual cDevice *Attach(cDevice *ParentDevice, const char *DevPath) = 0;
+ ///< Probes for a device at the given device-path like /dev/dvb/adapter0/frontend0
+ ///< or /dev/video0 etc. and creates the appropriate
+ ///< object derived from cDevice if applicable.
+ ///< Returns the device that has been created or NULL if not.
+ ///< The dynamite-plugin will delete the device if it is detached.
+ };
+
+extern cList<cDynamicDeviceProbe> DynamicDeviceProbes;
+
#endif //__DEVICE_H
diff --git a/dvbci.c b/dvbci.c
index 5289bbd..ea54bdb 100644
--- a/dvbci.c
+++ b/dvbci.c
@@ -41,6 +41,8 @@ cDvbCiAdapter::cDvbCiAdapter(cDevice *Device, int Fd)
cDvbCiAdapter::~cDvbCiAdapter()
{
Cancel(3);
+ if (device->IsSubDevice() || device->HasSubDevice())
+ close(fd);
}
int cDvbCiAdapter::Read(uint8_t *Buffer, int MaxLength)
diff --git a/dvbdevice.c b/dvbdevice.c
index f32b350..df2e679 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -259,6 +259,7 @@ private:
int device;
int fd_frontend;
int adapter, frontend;
+ cDvbDevice *dvbdevice;
int tuneTimeout;
int lockTimeout;
time_t lastTimeoutReport;
@@ -273,7 +274,7 @@ private:
bool SetFrontend(void);
virtual void Action(void);
public:
- cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType);
+ cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType, cDvbDevice *Dvbdevice);
virtual ~cDvbTuner();
const cChannel *GetTransponder(void) const { return &channel; }
bool IsTunedTo(const cChannel *Channel) const;
@@ -281,13 +282,14 @@ public:
bool Locked(int TimeoutMs = 0);
};
-cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType)
+cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType, cDvbDevice *Dvbdevice)
{
device = Device;
fd_frontend = Fd_Frontend;
adapter = Adapter;
frontend = Frontend;
frontendType = FrontendType;
+ dvbdevice = Dvbdevice;
tuneTimeout = 0;
lockTimeout = 0;
lastTimeoutReport = 0;
@@ -305,6 +307,8 @@ cDvbTuner::~cDvbTuner()
newSet.Broadcast();
locked.Broadcast();
Cancel(3);
+ if (dvbdevice && dvbdevice->IsSubDevice())
+ close(fd_frontend);
}
bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
@@ -661,7 +665,8 @@ const char *DeliverySystems[] = {
NULL
};
-cDvbDevice::cDvbDevice(int Adapter, int Frontend)
+cDvbDevice::cDvbDevice(int Adapter, int Frontend, cDevice *ParentDevice)
+:cDevice(ParentDevice)
{
adapter = Adapter;
frontend = Frontend;
@@ -678,7 +683,7 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend)
fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR);
if (fd_ca >= 0)
- ciAdapter = cDvbCiAdapter::CreateCiAdapter(this, fd_ca);
+ ciAdapter = cDvbCiAdapter::CreateCiAdapter(parentDevice ? parentDevice : this, fd_ca);
// The DVR device (will be opened and closed as needed):
@@ -718,7 +723,7 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend)
else
p = (char *)"unknown modulations";
isyslog("frontend %d/%d provides %s with %s (\"%s\")", adapter, frontend, DeliverySystems[frontendType], p, frontendInfo.name);
- dvbTuner = new cDvbTuner(CardIndex() + 1, fd_frontend, adapter, frontend, frontendType);
+ dvbTuner = new cDvbTuner(CardIndex() + 1, fd_frontend, adapter, frontend, frontendType, this);
}
}
else
diff --git a/dvbdevice.h b/dvbdevice.h
index ff606fd..0ac3a24 100644
--- a/dvbdevice.h
+++ b/dvbdevice.h
@@ -123,7 +123,7 @@ private:
fe_delivery_system frontendType;
int fd_dvr, fd_ca;
public:
- cDvbDevice(int Adapter, int Frontend);
+ cDvbDevice(int Adapter, int Frontend, cDevice *ParentDevice = NULL);
virtual ~cDvbDevice();
virtual bool Ready(void);
|