1 /* 2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de> 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, 8 * merge, publish, distribute, sublicense, and/or sell copies of 9 * the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 #include "DVBMediaAddon.h" 26 #include "DVBCard.h" 27 #include "DVBMediaNode.h" 28 #include "config.h" 29 30 #include <string.h> 31 #include <stdio.h> 32 #include <time.h> 33 #include <Alert.h> 34 #include <Directory.h> 35 #include <Entry.h> 36 #include <Path.h> 37 38 struct device_info 39 { 40 DVBCard * card; 41 char name[200]; 42 char info[200]; 43 media_format formats[5]; 44 flavor_info flavor; 45 }; 46 47 48 extern "C" BMediaAddOn * 49 make_media_addon(image_id id) 50 { 51 return new DVBMediaAddon(id); 52 } 53 54 55 DVBMediaAddon::DVBMediaAddon(image_id id) 56 : BMediaAddOn(id) 57 { 58 ScanFolder("/dev/dvb"); 59 } 60 61 62 DVBMediaAddon::~DVBMediaAddon() 63 { 64 FreeDeviceList(); 65 } 66 67 68 status_t 69 DVBMediaAddon::InitCheck(const char ** out_failure_text) 70 { 71 if (!fDeviceList.CountItems()) { 72 *out_failure_text = "No supported device found"; 73 return B_ERROR; 74 } 75 return B_OK; 76 } 77 78 79 int32 80 DVBMediaAddon::CountFlavors() 81 { 82 return fDeviceList.CountItems(); 83 } 84 85 86 status_t 87 DVBMediaAddon::GetFlavorAt(int32 n, const flavor_info ** out_info) 88 { 89 device_info *dev = (device_info *)fDeviceList.ItemAt(n); 90 if (!dev) 91 return B_ERROR; 92 *out_info = &dev->flavor; 93 return B_OK; 94 } 95 96 97 BMediaNode * 98 DVBMediaAddon::InstantiateNodeFor(const flavor_info * info, BMessage * config, status_t * out_error) 99 { 100 printf("DVB: DVBMediaAddon::InstantiateNodeFor\n"); 101 102 device_info *dev = (device_info *)fDeviceList.ItemAt(info->internal_id); 103 if (!dev || dev->flavor.internal_id != info->internal_id) { 104 *out_error = B_ERROR; 105 return NULL; 106 } 107 *out_error = B_OK; 108 109 return new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card); 110 } 111 112 113 bool 114 DVBMediaAddon::WantsAutoStart() 115 { 116 #if BUILD_FOR_HAIKU 117 printf("DVB: DVBMediaAddon::WantsAutoStart - NO\n"); 118 return false; 119 #else 120 printf("DVB: DVBMediaAddon::WantsAutoStart - YES\n"); 121 return true; 122 #endif 123 } 124 125 126 status_t 127 DVBMediaAddon::AutoStart(int index, BMediaNode **outNode, int32 *outInternalID, bool *outHasMore) 128 { 129 printf("DVB: DVBMediaAddon::AutoStart, index %d\n", index); 130 131 #if BUILD_FOR_HAIKU 132 return B_ERROR; 133 #else 134 135 device_info *dev = (device_info *)fDeviceList.ItemAt(index); 136 if (!dev) { 137 printf("DVB: DVBMediaAddon::AutoStart, bad index\n"); 138 return B_BAD_INDEX; 139 } 140 141 *outHasMore = fDeviceList.ItemAt(index + 1) ? true : false; 142 *outInternalID = dev->flavor.internal_id; 143 *outNode = new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card); 144 145 printf("DVB: DVBMediaAddon::AutoStart, success\n"); 146 147 return B_OK; 148 #endif 149 } 150 151 152 void 153 DVBMediaAddon::ScanFolder(const char *path) 154 { 155 BDirectory dir(path); 156 if (dir.InitCheck() != B_OK) 157 return; 158 159 BEntry ent; 160 161 while (dir.GetNextEntry(&ent) == B_OK) { 162 BPath path(&ent); 163 if (ent.IsDirectory()) { 164 ScanFolder(path.Path()); 165 } else { 166 DVBCard *card = new DVBCard(path.Path()); 167 if (card->InitCheck() == B_OK) 168 AddDevice(card, path.Path()); 169 else 170 delete card; 171 } 172 } 173 } 174 175 176 void 177 DVBMediaAddon::AddDevice(DVBCard *card, const char *path) 178 { 179 dvb_type_t type; 180 char name[250]; 181 char info[1000]; 182 const char *dvbtype; 183 const char *dvbnumber; 184 185 // get card name, info and type 186 if (B_OK != card->GetCardType(&type)) { 187 printf("DVBMediaAddon::AddDevice: getting DVB card type failed\n"); 188 return; 189 } 190 if (B_OK != card->GetCardInfo(name, sizeof(name), info, sizeof(info))) { 191 printf("DVBMediaAddon::AddDevice: getting DVB card info failed\n"); 192 return; 193 } 194 195 // get type 196 switch (type) { 197 case DVB_TYPE_DVB_C: dvbtype = "C"; break; 198 case DVB_TYPE_DVB_H: dvbtype = "H"; break; 199 case DVB_TYPE_DVB_S: dvbtype = "S"; break; 200 case DVB_TYPE_DVB_T: dvbtype = "T"; break; 201 default: 202 printf("DVBMediaAddon::AddDevice: unsupported DVB type %d\n", type); 203 return; 204 } 205 206 // get interface number 207 const char *p = strrchr(path, '/'); 208 dvbnumber = p ? p + 1 : ""; 209 210 // create device_info 211 device_info *dev = new device_info; 212 fDeviceList.AddItem(dev); 213 214 dev->card = card; 215 216 // setup name and info, it's important that name starts with "DVB" 217 // snprintf(dev->name, sizeof(dev->name), "DVB-%s %s (%s)", dvbtype, dvbnumber, name); 218 // strlcpy(dev->info, info, sizeof(dev->info)); 219 sprintf(dev->name, "DVB-%s %s %s", dvbtype, name, dvbnumber); 220 strcpy(dev->info, info); 221 222 // setup supported formats (the lazy way) 223 memset(dev->formats, 0, sizeof(dev->formats)); 224 dev->formats[0].type = B_MEDIA_RAW_VIDEO; 225 dev->formats[1].type = B_MEDIA_RAW_AUDIO; 226 dev->formats[2].type = B_MEDIA_ENCODED_VIDEO; 227 dev->formats[3].type = B_MEDIA_ENCODED_AUDIO; 228 dev->formats[4].type = B_MEDIA_MULTISTREAM; 229 230 // setup flavor info 231 dev->flavor.name = dev->name; 232 dev->flavor.info = dev->info; 233 dev->flavor.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT; 234 dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL; 235 dev->flavor.internal_id = fDeviceList.CountItems() - 1; 236 dev->flavor.possible_count = 1; 237 dev->flavor.in_format_count = 0; 238 dev->flavor.in_format_flags = 0; 239 dev->flavor.in_formats = 0; 240 dev->flavor.out_format_count = 5; 241 dev->flavor.out_format_flags = 0; 242 dev->flavor.out_formats = dev->formats; 243 } 244 245 246 void 247 DVBMediaAddon::FreeDeviceList() 248 { 249 device_info *dev; 250 while ((dev = (device_info *)fDeviceList.RemoveItem((int32)0))) { 251 delete dev->card; 252 delete dev; 253 } 254 } 255