xref: /haiku/src/add-ons/media/media-add-ons/firewire_dv/FireWireDVAddOn.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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 
26 struct 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 
35 extern "C" BMediaAddOn*
36 make_media_addon(image_id id)
37 {
38 	CALLED();
39 	return new FireWireDVAddOn(id);
40 }
41 
42 
43 FireWireDVAddOn::FireWireDVAddOn(image_id id)
44 	: BMediaAddOn(id)
45 {
46 	CALLED();
47 	ScanFolder("/dev/bus/fw");
48 }
49 
50 
51 FireWireDVAddOn::~FireWireDVAddOn()
52 {
53 	CALLED();
54 	FreeDeviceList();
55 }
56 
57 
58 status_t
59 FireWireDVAddOn::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 
70 int32
71 FireWireDVAddOn::CountFlavors()
72 {
73 	CALLED();
74 	return fDeviceList.CountItems();
75 }
76 
77 
78 status_t
79 FireWireDVAddOn::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 
90 BMediaNode *
91 FireWireDVAddOn::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 
107 bool
108 FireWireDVAddOn::WantsAutoStart()
109 {
110 	CALLED();
111 	return false;
112 }
113 
114 
115 status_t
116 FireWireDVAddOn::AutoStart(int index, BMediaNode** outNode,
117 	int32* outInternalID, bool* outHasMore)
118 {
119 	CALLED();
120 	return B_ERROR;
121 }
122 
123 
124 void
125 FireWireDVAddOn::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 
147 void
148 FireWireDVAddOn::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 
189 void
190 FireWireDVAddOn::FreeDeviceList()
191 {
192 	device_info* dev;
193 	while ((dev = fDeviceList.RemoveItemAt(0L))) {
194 		delete dev->card;
195 		delete dev;
196 	}
197 }
198 
199