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
20WebCamMediaAddOn::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
44WebCamMediaAddOn::~WebCamMediaAddOn()
45{
46	fRoster->Stop();
47	delete fRoster;
48}
49
50
51status_t
52WebCamMediaAddOn::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
63int32
64WebCamMediaAddOn::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 */
84status_t
85WebCamMediaAddOn::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
111BMediaNode *
112WebCamMediaAddOn::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
157status_t
158WebCamMediaAddOn::CameraAdded(CamDevice* device)
159{
160	PRINT((CH "()" CT));
161	NotifyFlavorChange();
162	return B_OK;
163}
164
165
166status_t
167WebCamMediaAddOn::CameraRemoved(CamDevice* device)
168{
169	PRINT((CH "()" CT));
170	NotifyFlavorChange();
171	return B_OK;
172}
173
174
175void
176WebCamMediaAddOn::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
193BMediaAddOn *
194make_media_addon(image_id id)
195{
196	return new WebCamMediaAddOn(id);
197}
198