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