xref: /haiku/src/add-ons/media/media-add-ons/usb_webcam/AddOn.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 /*
2  * Copyright 2004-2008, François Revol, <revol@free.fr>.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <support/Autolock.h>
7 #include <media/MediaFormats.h>
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12 
13 #include "AddOn.h"
14 #include "Producer.h"
15 #include "CamRoster.h"
16 #include "CamDebug.h"
17 #include "CamDevice.h"
18 
19 
20 WebCamMediaAddOn::WebCamMediaAddOn(image_id imid)
21 	: BMediaAddOn(imid),
22 	fInitStatus(B_NO_INIT),
23 	fRoster(NULL)
24 {
25 	PRINT((CH "()" CT));
26 	fInternalIDCounter = 0;
27 	/* Customize these parameters to match those of your node */
28 	fMediaFormat.type = B_MEDIA_RAW_VIDEO;
29 	fMediaFormat.u.raw_video = media_raw_video_format::wildcard;
30 	fMediaFormat.u.raw_video.interlace = 1;
31 	fMediaFormat.u.raw_video.display.format = B_RGB32;
32 	FillDefaultFlavorInfo(&fDefaultFlavorInfo);
33 
34 	fRoster = new CamRoster(this);
35 	fRoster->Start();
36 //	if( fRoster->CountCameras() < 1 )
37 /*		fInitStatus = B_ERROR;
38 	else
39 */
40 		fInitStatus = B_OK;
41 }
42 
43 
44 WebCamMediaAddOn::~WebCamMediaAddOn()
45 {
46 	fRoster->Stop();
47 	delete fRoster;
48 }
49 
50 
51 status_t
52 WebCamMediaAddOn::InitCheck(const char **out_failure_text)
53 {
54 	if (fInitStatus < B_OK) {
55 		*out_failure_text = "No cameras attached";
56 		return fInitStatus;
57 	}
58 
59 	return B_OK;
60 }
61 
62 
63 int32
64 WebCamMediaAddOn::CountFlavors()
65 {
66 	PRINT((CH "()" CT));
67 	int32 count;
68 	if (!fRoster)
69 		return B_NO_INIT;
70 	if (fInitStatus < B_OK)
71 		return fInitStatus;
72 
73 	/* This addon only supports a single flavor, as defined in the
74 	 * constructor */
75 	count = fRoster->CountCameras();
76 	return count;//(count > 0)?count:1;//1;
77 }
78 
79 
80 /*
81  * The pointer to the flavor received only needs to be valid between
82  * successive calls to BMediaAddOn::GetFlavorAt().
83  */
84 status_t
85 WebCamMediaAddOn::GetFlavorAt(int32 n, const flavor_info **out_info)
86 {
87 	PRINT((CH "(%d, ) roster %p is %" B_PRIx32 CT, n, fRoster, fInitStatus));
88 	int32 count;
89 	CamDevice* cam;
90 	if (!fRoster)
91 		return B_NO_INIT;
92 	if (fInitStatus < B_OK)
93 		return fInitStatus;
94 
95 	count = fRoster->CountCameras();
96 	PRINT((CH ": %d cameras" CT, count));
97 	if (n >= count)//(n != 0)
98 		return B_BAD_INDEX;
99 
100 	fRoster->Lock();
101 	cam = fRoster->CameraAt(n);
102 	*out_info = &fDefaultFlavorInfo;
103 	if (cam && cam->FlavorInfo())
104 		*out_info = cam->FlavorInfo();
105 	fRoster->Unlock();
106 	PRINT((CH ": returning flavor for %d, internal_id %d" CT, n, (*out_info)->internal_id));
107 	return B_OK;
108 }
109 
110 
111 BMediaNode *
112 WebCamMediaAddOn::InstantiateNodeFor(
113 		const flavor_info *info, BMessage* /*_config*/, status_t* /*_out_error*/)
114 {
115 	PRINT((CH "()" CT));
116 	VideoProducer *node;
117 	CamDevice *cam=NULL;
118 
119 	if (fInitStatus < B_OK)
120 		return NULL;
121 
122 	fRoster->Lock();
123 	for (uint32 i = 0; i < fRoster->CountCameras(); i++) {
124 		CamDevice *c;
125 		c = fRoster->CameraAt(i);
126 		PRINT((CH ": cam[%d]: %d, %s" CT, i, c->FlavorInfo()->internal_id, c->BrandName()));
127 		if (c && (c->FlavorInfo()->internal_id == info->internal_id)) {
128 			cam = c;
129 			break;
130 		}
131 	}
132 	fRoster->Unlock();
133 	if (!cam)
134 		return NULL;
135 
136 #if 0
137 	fRoster->Lock();
138 	cam = fRoster->CameraAt(n);
139 	*out_info = &fDefaultFlavorInfo;
140 	if (cam && cam->FlavorInfo())
141 		*out_info = cam->FlavorInfo();
142 	fRoster->Unlock();
143 #endif
144 	/* At most one instance of the node should be instantiated at any given
145 	 * time. The locking for this restriction may be found in the VideoProducer
146 	 * class. */
147 	node = new VideoProducer(this, cam, cam->FlavorInfo()->name, cam->FlavorInfo()->internal_id);
148 	if (node && (node->InitCheck() < B_OK)) {
149 		delete node;
150 		node = NULL;
151 	}
152 
153 	return node;
154 }
155 
156 
157 status_t
158 WebCamMediaAddOn::CameraAdded(CamDevice* device)
159 {
160 	PRINT((CH "()" CT));
161 	NotifyFlavorChange();
162 	return B_OK;
163 }
164 
165 
166 status_t
167 WebCamMediaAddOn::CameraRemoved(CamDevice* device)
168 {
169 	PRINT((CH "()" CT));
170 	NotifyFlavorChange();
171 	return B_OK;
172 }
173 
174 
175 void
176 WebCamMediaAddOn::FillDefaultFlavorInfo(flavor_info* info)
177 {
178 	info->name = (char *)"USB Web Camera";
179 	info->info = (char *)"USB Web Camera";
180 	info->kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT;
181 	info->flavor_flags = 0;//B_FLAVOR_IS_GLOBAL;
182 	info->internal_id = atomic_add((int32*)&fInternalIDCounter, 1);
183 	info->possible_count = 1;//0;
184 	info->in_format_count = 0;
185 	info->in_format_flags = 0;
186 	info->in_formats = NULL;
187 	info->out_format_count = 1;
188 	info->out_format_flags = 0;
189 	info->out_formats = &fMediaFormat;
190 }
191 
192 
193 BMediaAddOn *
194 make_media_addon(image_id id)
195 {
196 	return new WebCamMediaAddOn(id);
197 }
198