1/*
2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include "DVBMediaAddon.h"
26#include "DVBCard.h"
27#include "DVBMediaNode.h"
28#include "config.h"
29
30#include <string.h>
31#include <stdio.h>
32#include <time.h>
33#include <Alert.h>
34#include <Directory.h>
35#include <Entry.h>
36#include <Path.h>
37
38struct device_info
39{
40	DVBCard *		card;
41	char			name[200];
42	char			info[200];
43	media_format 	formats[5];
44	flavor_info 	flavor;
45};
46
47
48extern "C" BMediaAddOn *
49make_media_addon(image_id id)
50{
51	return new DVBMediaAddon(id);
52}
53
54
55DVBMediaAddon::DVBMediaAddon(image_id id)
56 :	BMediaAddOn(id)
57{
58	ScanFolder("/dev/dvb");
59}
60
61
62DVBMediaAddon::~DVBMediaAddon()
63{
64	FreeDeviceList();
65}
66
67
68status_t
69DVBMediaAddon::InitCheck(const char ** out_failure_text)
70{
71	if (!fDeviceList.CountItems()) {
72		*out_failure_text = "No supported device found";
73		return B_ERROR;
74	}
75	return B_OK;
76}
77
78
79int32
80DVBMediaAddon::CountFlavors()
81{
82	return fDeviceList.CountItems();
83}
84
85
86status_t
87DVBMediaAddon::GetFlavorAt(int32 n, const flavor_info ** out_info)
88{
89	device_info *dev = (device_info *)fDeviceList.ItemAt(n);
90	if (!dev)
91		return B_ERROR;
92	*out_info = &dev->flavor;
93	return B_OK;
94}
95
96
97BMediaNode *
98DVBMediaAddon::InstantiateNodeFor(const flavor_info * info, BMessage * config,	status_t * out_error)
99{
100	printf("DVB: DVBMediaAddon::InstantiateNodeFor\n");
101
102	device_info *dev = (device_info *)fDeviceList.ItemAt(info->internal_id);
103	if (!dev || dev->flavor.internal_id != info->internal_id) {
104		*out_error = B_ERROR;
105		return NULL;
106	}
107	*out_error = B_OK;
108
109	return new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card);
110}
111
112
113bool
114DVBMediaAddon::WantsAutoStart()
115{
116#if BUILD_FOR_HAIKU
117//	printf("DVB: DVBMediaAddon::WantsAutoStart - NO\n");
118	return false;
119#else
120//	printf("DVB: DVBMediaAddon::WantsAutoStart - YES\n");
121	return true;
122#endif
123}
124
125
126status_t
127DVBMediaAddon::AutoStart(int index, BMediaNode **outNode, int32 *outInternalID, bool *outHasMore)
128{
129	printf("DVB: DVBMediaAddon::AutoStart, index %d\n", index);
130
131#if BUILD_FOR_HAIKU
132	return B_ERROR;
133#else
134
135	device_info *dev = (device_info *)fDeviceList.ItemAt(index);
136	if (!dev) {
137		printf("DVB: DVBMediaAddon::AutoStart, bad index\n");
138		return B_BAD_INDEX;
139	}
140
141	*outHasMore = fDeviceList.ItemAt(index + 1) ? true : false;
142	*outInternalID = dev->flavor.internal_id;
143	*outNode = new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card);
144
145	printf("DVB: DVBMediaAddon::AutoStart, success\n");
146
147	return B_OK;
148#endif
149}
150
151
152void
153DVBMediaAddon::ScanFolder(const char *path)
154{
155	BDirectory dir(path);
156	if (dir.InitCheck() != B_OK)
157		return;
158
159	BEntry ent;
160
161	while (dir.GetNextEntry(&ent) == B_OK) {
162		BPath path(&ent);
163		if (ent.IsDirectory()) {
164			ScanFolder(path.Path());
165		} else {
166			DVBCard *card = new DVBCard(path.Path());
167			if (card->InitCheck() == B_OK)
168				AddDevice(card, path.Path());
169			else
170				delete card;
171		}
172	}
173}
174
175
176void
177DVBMediaAddon::AddDevice(DVBCard *card, const char *path)
178{
179	dvb_type_t type;
180	char name[250];
181	char info[1000];
182	const char *dvbtype;
183	const char *dvbnumber;
184
185	// get card name, info and type
186	if (B_OK != card->GetCardType(&type)) {
187		printf("DVBMediaAddon::AddDevice: getting DVB card type failed\n");
188		return;
189	}
190	if (B_OK != card->GetCardInfo(name, sizeof(name), info, sizeof(info))) {
191		printf("DVBMediaAddon::AddDevice: getting DVB card info failed\n");
192		return;
193	}
194
195	// get type
196	switch (type) {
197		case DVB_TYPE_DVB_C: dvbtype = "C"; break;
198		case DVB_TYPE_DVB_H: dvbtype = "H"; break;
199		case DVB_TYPE_DVB_S: dvbtype = "S"; break;
200		case DVB_TYPE_DVB_T: dvbtype = "T"; break;
201		default:
202			printf("DVBMediaAddon::AddDevice: unsupported DVB type %d\n", type);
203			return;
204	}
205
206	// get interface number
207	const char *p = strrchr(path, '/');
208	dvbnumber = p ? p + 1 : "";
209
210	// create device_info
211	device_info *dev = new device_info;
212	fDeviceList.AddItem(dev);
213
214	dev->card = card;
215
216	// setup name and info, it's important that name starts with "DVB"
217//	snprintf(dev->name, sizeof(dev->name), "DVB-%s %s (%s)", dvbtype, dvbnumber, name);
218//	strlcpy(dev->info, info, sizeof(dev->info));
219	sprintf(dev->name, "DVB-%s %s %s", dvbtype, name, dvbnumber);
220	strcpy(dev->info, info);
221
222	// setup supported formats (the lazy way)
223	memset(dev->formats, 0, sizeof(dev->formats));
224	dev->formats[0].type = B_MEDIA_RAW_VIDEO;
225	dev->formats[1].type = B_MEDIA_RAW_AUDIO;
226	dev->formats[2].type = B_MEDIA_ENCODED_VIDEO;
227	dev->formats[3].type = B_MEDIA_ENCODED_AUDIO;
228	dev->formats[4].type = B_MEDIA_MULTISTREAM;
229
230	// setup flavor info
231	dev->flavor.name = dev->name;
232	dev->flavor.info = dev->info;
233	dev->flavor.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT;
234	dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
235	dev->flavor.internal_id = fDeviceList.CountItems() - 1;
236	dev->flavor.possible_count = 1;
237	dev->flavor.in_format_count = 0;
238	dev->flavor.in_format_flags = 0;
239	dev->flavor.in_formats = 0;
240	dev->flavor.out_format_count = 5;
241	dev->flavor.out_format_flags = 0;
242	dev->flavor.out_formats = dev->formats;
243}
244
245
246void
247DVBMediaAddon::FreeDeviceList()
248{
249	device_info *dev;
250	while ((dev = (device_info *)fDeviceList.RemoveItem((int32)0))) {
251		delete dev->card;
252		delete dev;
253	}
254}
255