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	debugger("");
72	if (!fDeviceList.CountItems()) {
73		*out_failure_text = "No supported device found";
74		return B_ERROR;
75	}
76
77	return B_OK;
78}
79
80
81int32
82DVBMediaAddon::CountFlavors()
83{
84	return fDeviceList.CountItems();
85}
86
87
88status_t
89DVBMediaAddon::GetFlavorAt(int32 n, const flavor_info ** out_info)
90{
91	device_info *dev = (device_info *)fDeviceList.ItemAt(n);
92	if (!dev)
93		return B_ERROR;
94	*out_info = &dev->flavor;
95	return B_OK;
96}
97
98
99BMediaNode *
100DVBMediaAddon::InstantiateNodeFor(const flavor_info * info, BMessage * config,	status_t * out_error)
101{
102	printf("DVB: DVBMediaAddon::InstantiateNodeFor\n");
103
104	device_info *dev = (device_info *)fDeviceList.ItemAt(info->internal_id);
105	if (!dev || dev->flavor.internal_id != info->internal_id) {
106		*out_error = B_ERROR;
107		return NULL;
108	}
109	*out_error = B_OK;
110
111	return new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card);
112}
113
114
115bool
116DVBMediaAddon::WantsAutoStart()
117{
118#if BUILD_FOR_HAIKU
119//	printf("DVB: DVBMediaAddon::WantsAutoStart - NO\n");
120	return false;
121#else
122//	printf("DVB: DVBMediaAddon::WantsAutoStart - YES\n");
123	return true;
124#endif
125}
126
127
128status_t
129DVBMediaAddon::AutoStart(int index, BMediaNode **outNode, int32 *outInternalID, bool *outHasMore)
130{
131	printf("DVB: DVBMediaAddon::AutoStart, index %d\n", index);
132
133#if BUILD_FOR_HAIKU
134	return B_ERROR;
135#else
136
137	device_info *dev = (device_info *)fDeviceList.ItemAt(index);
138	if (!dev) {
139		printf("DVB: DVBMediaAddon::AutoStart, bad index\n");
140		return B_BAD_INDEX;
141	}
142
143	*outHasMore = fDeviceList.ItemAt(index + 1) ? true : false;
144	*outInternalID = dev->flavor.internal_id;
145	*outNode = new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card);
146
147	printf("DVB: DVBMediaAddon::AutoStart, success\n");
148
149	return B_OK;
150#endif
151}
152
153
154void
155DVBMediaAddon::ScanFolder(const char *path)
156{
157	BDirectory dir(path);
158	if (dir.InitCheck() != B_OK)
159		return;
160
161	BEntry ent;
162
163	while (dir.GetNextEntry(&ent) == B_OK) {
164		BPath path(&ent);
165		if (ent.IsDirectory()) {
166			ScanFolder(path.Path());
167		} else {
168			DVBCard *card = new DVBCard(path.Path());
169			if (card->InitCheck() == B_OK)
170				AddDevice(card, path.Path());
171			else
172				delete card;
173		}
174	}
175}
176
177
178void
179DVBMediaAddon::AddDevice(DVBCard *card, const char *path)
180{
181	dvb_type_t type;
182	char name[250];
183	char info[1000];
184	const char *dvbtype;
185	const char *dvbnumber;
186
187	// get card name, info and type
188	if (B_OK != card->GetCardType(&type)) {
189		printf("DVBMediaAddon::AddDevice: getting DVB card type failed\n");
190		return;
191	}
192	if (B_OK != card->GetCardInfo(name, sizeof(name), info, sizeof(info))) {
193		printf("DVBMediaAddon::AddDevice: getting DVB card info failed\n");
194		return;
195	}
196
197	// get type
198	switch (type) {
199		case DVB_TYPE_DVB_C: dvbtype = "C"; break;
200		case DVB_TYPE_DVB_H: dvbtype = "H"; break;
201		case DVB_TYPE_DVB_S: dvbtype = "S"; break;
202		case DVB_TYPE_DVB_T: dvbtype = "T"; break;
203		default:
204			printf("DVBMediaAddon::AddDevice: unsupported DVB type %d\n", type);
205			return;
206	}
207
208	// get interface number
209	const char *p = strrchr(path, '/');
210	dvbnumber = p ? p + 1 : "";
211
212	// create device_info
213	device_info *dev = new device_info;
214	fDeviceList.AddItem(dev);
215
216	dev->card = card;
217
218	// setup name and info, it's important that name starts with "DVB"
219//	snprintf(dev->name, sizeof(dev->name), "DVB-%s %s (%s)", dvbtype, dvbnumber, name);
220//	strlcpy(dev->info, info, sizeof(dev->info));
221	sprintf(dev->name, "DVB-%s %s %s", dvbtype, name, dvbnumber);
222	strcpy(dev->info, info);
223
224	// setup supported formats (the lazy way)
225	memset(dev->formats, 0, sizeof(dev->formats));
226	dev->formats[0].type = B_MEDIA_RAW_VIDEO;
227	dev->formats[1].type = B_MEDIA_RAW_AUDIO;
228	dev->formats[2].type = B_MEDIA_ENCODED_VIDEO;
229	dev->formats[3].type = B_MEDIA_ENCODED_AUDIO;
230	dev->formats[4].type = B_MEDIA_MULTISTREAM;
231
232	// setup flavor info
233	dev->flavor.name = dev->name;
234	dev->flavor.info = dev->info;
235	dev->flavor.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT;
236	dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
237	dev->flavor.internal_id = fDeviceList.CountItems() - 1;
238	dev->flavor.possible_count = 1;
239	dev->flavor.in_format_count = 0;
240	dev->flavor.in_format_flags = 0;
241	dev->flavor.in_formats = 0;
242	dev->flavor.out_format_count = 5;
243	dev->flavor.out_format_flags = 0;
244	dev->flavor.out_formats = dev->formats;
245}
246
247
248void
249DVBMediaAddon::FreeDeviceList()
250{
251	device_info *dev;
252	while ((dev = (device_info *)fDeviceList.RemoveItem((int32)0))) {
253		delete dev->card;
254		delete dev;
255	}
256}
257