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