1/*
2 * FireWire DV media addon for Haiku
3 *
4 * Copyright (c) 2008, JiSheng Zhang (jszhang3@mail.ustc.edu.cn)
5 * Distributed under the terms of the MIT License.
6 *
7 * Based on DVB media addon
8 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
9 */
10
11#include "FireWireDVAddOn.h"
12#include "FireWireCard.h"
13#include "FireWireDVNode.h"
14
15#include <stdio.h>
16#include <string.h>
17#include <time.h>
18
19#include <Alert.h>
20#include <Directory.h>
21#include <Entry.h>
22#include <Path.h>
23
24#include "debug.h"
25
26struct device_info
27{
28	FireWireCard*	card;
29	char		name[16];
30	media_format 	in_formats[1];
31	media_format 	out_formats[1];
32	flavor_info 	flavor;
33};
34
35extern "C" BMediaAddOn*
36make_media_addon(image_id id)
37{
38	CALLED();
39	return new FireWireDVAddOn(id);
40}
41
42
43FireWireDVAddOn::FireWireDVAddOn(image_id id)
44	: BMediaAddOn(id)
45{
46	CALLED();
47	ScanFolder("/dev/bus/fw");
48}
49
50
51FireWireDVAddOn::~FireWireDVAddOn()
52{
53	CALLED();
54	FreeDeviceList();
55}
56
57
58status_t
59FireWireDVAddOn::InitCheck(const char** out_failure_text)
60{
61	CALLED();
62	if (!fDeviceList.CountItems()) {
63		*out_failure_text = "No supported device found";
64		return B_ERROR;
65	}
66	return B_OK;
67}
68
69
70int32
71FireWireDVAddOn::CountFlavors()
72{
73	CALLED();
74	return fDeviceList.CountItems();
75}
76
77
78status_t
79FireWireDVAddOn::GetFlavorAt(int32 n, const flavor_info** out_info)
80{
81	CALLED();
82	device_info* dev = fDeviceList.ItemAt(n);
83	if (!dev)
84		return B_ERROR;
85	*out_info = &dev->flavor;
86	return B_OK;
87}
88
89
90BMediaNode *
91FireWireDVAddOn::InstantiateNodeFor(const flavor_info* info, BMessage* config,
92	status_t* out_error)
93{
94	CALLED();
95	device_info* dev = fDeviceList.ItemAt(info->internal_id);
96	if (!dev || dev->flavor.internal_id != info->internal_id) {
97		*out_error = B_ERROR;
98		return NULL;
99	}
100	*out_error = B_OK;
101
102	return new FireWireDVNode(this, dev->name, dev->flavor.internal_id,
103		dev->card);
104}
105
106
107bool
108FireWireDVAddOn::WantsAutoStart()
109{
110	CALLED();
111	return false;
112}
113
114
115status_t
116FireWireDVAddOn::AutoStart(int index, BMediaNode** outNode,
117	int32* outInternalID, bool* outHasMore)
118{
119	CALLED();
120	return B_ERROR;
121}
122
123
124void
125FireWireDVAddOn::ScanFolder(const char* path)
126{
127	CALLED();
128	BDirectory dir(path);
129	if (dir.InitCheck() != B_OK)
130		return;
131
132	BEntry ent;
133
134	while (dir.GetNextEntry(&ent) == B_OK) {
135		BPath path(&ent);
136		if (!ent.IsDirectory() && !ent.IsSymLink()) {
137			FireWireCard *card = new FireWireCard(path.Path());
138			if (card->InitCheck() == B_OK)
139				AddDevice(card, path.Path());
140			else
141				delete card;
142		}
143	}
144}
145
146
147void
148FireWireDVAddOn::AddDevice(FireWireCard* card, const char* path)
149{
150	const char* fwnumber;
151
152	// get card name, info and type
153
154	// get interface number
155	const char *p = strrchr(path, '/');
156	fwnumber = p ? p + 1 : "";
157
158	// create device_info
159	device_info *dev = new device_info;
160	fDeviceList.AddItem(dev);
161
162	dev->card = card;
163
164	sprintf(dev->name, "FireWire-%s", fwnumber);
165
166	// setup supported formats (the lazy way)
167	memset(dev->in_formats, 0, sizeof(dev->in_formats));
168	memset(dev->out_formats, 0, sizeof(dev->out_formats));
169	dev->in_formats[0].type = B_MEDIA_ENCODED_VIDEO;
170	dev->out_formats[0].type = B_MEDIA_ENCODED_VIDEO;
171
172	// setup flavor info
173	dev->flavor.name = dev->name;
174	dev->flavor.info = (char *)"The FireWireDVNode outputs to fw_raw drivers.";
175	dev->flavor.kinds = B_BUFFER_CONSUMER | B_BUFFER_PRODUCER
176		| B_CONTROLLABLE | B_PHYSICAL_OUTPUT | B_PHYSICAL_INPUT;
177	dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
178	dev->flavor.internal_id = fDeviceList.CountItems() - 1;
179	dev->flavor.possible_count = 1;
180	dev->flavor.in_format_count = 1;
181	dev->flavor.in_format_flags = 0;
182	dev->flavor.in_formats = dev->in_formats;
183	dev->flavor.out_format_count = 1;
184	dev->flavor.out_format_flags = 0;
185	dev->flavor.out_formats = dev->out_formats;
186}
187
188
189void
190FireWireDVAddOn::FreeDeviceList()
191{
192	device_info* dev;
193	while ((dev = fDeviceList.RemoveItemAt(0L))) {
194		delete dev->card;
195		delete dev;
196	}
197}
198
199