1 /* 2 * Copyright (c) 2002, 2003, 2008 Marcus Overhagen <Marcus@Overhagen.de> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files or portions 6 * thereof (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, subject 10 * to the following conditions: 11 * 12 * * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * * Redistributions in binary form must reproduce the above copyright notice 16 * in the binary, as well as this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided with 18 * the distribution. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 * 28 */ 29 30 31 #include <MediaAddOn.h> 32 #include <string.h> 33 #include <stdlib.h> 34 #include <new> 35 #include "MediaDebug.h" 36 #include "DataExchange.h" 37 38 39 #define MAX_FLAVOR_IN_FORMAT_COUNT 300 40 #define MAX_FLAVOR_OUT_FORMAT_COUNT 300 41 42 #define FLATTEN_MAGIC 'CODE' 43 #define FLATTEN_TYPECODE 'DFIT' 44 45 46 static char * 47 _newstrdup(const char *str) 48 { 49 if (str == NULL) 50 return NULL; 51 int len = strlen(str) + 1; 52 char *p = new(std::nothrow) char[len]; 53 if (p) 54 memcpy(p, str, len); 55 return p; 56 } 57 58 59 // #pragma mark - dormant_node_info 60 61 62 dormant_node_info::dormant_node_info() 63 : 64 addon(-1), 65 flavor_id(-1) 66 { 67 name[0] = '\0'; 68 } 69 70 71 dormant_node_info::~dormant_node_info() 72 { 73 } 74 75 76 // #pragma mark - flavor_info 77 78 79 /* DO NOT IMPLEMENT */ 80 /* 81 flavor_info &flavor_info::operator=(const flavor_info &other) 82 */ 83 84 85 // #pragma mark - dormant_flavor_info 86 87 88 dormant_flavor_info::dormant_flavor_info() 89 { 90 name = NULL; 91 info = NULL; 92 kinds = 0; 93 flavor_flags = 0; 94 internal_id = 0; 95 possible_count = 0; 96 in_format_count = 0; 97 in_format_flags = 0; 98 in_formats = NULL; 99 out_format_count = 0; 100 out_format_flags = 0; 101 out_formats = NULL; 102 } 103 104 105 dormant_flavor_info::~dormant_flavor_info() 106 { 107 delete[] name; 108 delete[] info; 109 delete[] in_formats; 110 delete[] out_formats; 111 } 112 113 114 dormant_flavor_info::dormant_flavor_info(const dormant_flavor_info &clone) 115 { 116 name = NULL; 117 info = NULL; 118 in_formats = NULL; 119 out_formats = NULL; 120 121 *this = clone; 122 } 123 124 125 dormant_flavor_info & 126 dormant_flavor_info::operator=(const dormant_flavor_info &clone) 127 { 128 // call operator=(const flavor_info &clone) to copy the flavor_info base class 129 *this = static_cast<const flavor_info>(clone); 130 // copy the dormant_node_info member variable 131 node_info = clone.node_info; 132 return *this; 133 } 134 135 136 dormant_flavor_info & 137 dormant_flavor_info::operator=(const flavor_info &clone) 138 { 139 kinds = clone.kinds; 140 flavor_flags = clone.flavor_flags; 141 internal_id = clone.internal_id; 142 possible_count = clone.possible_count; 143 144 delete [] info; 145 info = _newstrdup(clone.info); 146 147 delete [] name; 148 name = _newstrdup(clone.name); 149 150 delete [] in_formats; 151 in_formats = NULL; 152 in_format_count = 0; 153 in_format_flags = clone.in_format_flags; 154 if ((kinds & B_BUFFER_CONSUMER) != 0) { 155 if (clone.in_format_count >= 0 156 && clone.in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT) { 157 in_formats = new(std::nothrow) media_format[clone.in_format_count]; 158 if (in_formats != NULL && clone.in_formats != NULL) { 159 in_format_count = clone.in_format_count; 160 for (int i = 0; i < in_format_count; i++) { 161 const_cast<media_format &>(in_formats[i]) 162 = clone.in_formats[i]; 163 } 164 } 165 } else { 166 fprintf(stderr, "error: dormant_flavor_info::operator= clone.in_" 167 "format_count is invalid\n"); 168 } 169 } else if (clone.in_format_count) { 170 fprintf(stderr, "warning: dormant_flavor_info::operator= not " 171 "B_BUFFER_CONSUMER and clone.in_format_count is != 0\n"); 172 } 173 174 delete [] out_formats; 175 out_formats = NULL; 176 out_format_count = 0; 177 out_format_flags = clone.out_format_flags; 178 if (kinds & B_BUFFER_PRODUCER) { 179 if (clone.out_format_count >= 0 180 && clone.out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { 181 out_formats = new(std::nothrow) media_format[clone.out_format_count]; 182 if (out_formats != NULL && clone.out_formats != NULL) { 183 out_format_count = clone.out_format_count; 184 for (int i = 0; i < out_format_count; i++) { 185 const_cast<media_format &>(out_formats[i]) 186 = clone.out_formats[i]; 187 } 188 } 189 } else { 190 fprintf(stderr, "error dormant_flavor_info::operator= clone.out_" 191 "format_count is invalid\n"); 192 } 193 } else if (clone.out_format_count) { 194 fprintf(stderr, "warning: dormant_flavor_info::operator= not " 195 "B_BUFFER_PRODUCER and clone.out_format_count is != 0\n"); 196 } 197 198 // initialize node_info with default values 199 dormant_node_info defaultValues; 200 node_info = defaultValues; 201 202 return *this; 203 } 204 205 206 void 207 dormant_flavor_info::set_name(const char *newName) 208 { 209 delete[] name; 210 name = _newstrdup(newName); 211 } 212 213 214 void 215 dormant_flavor_info::set_info(const char *newInfo) 216 { 217 delete[] info; 218 info = _newstrdup(newInfo); 219 } 220 221 222 void 223 dormant_flavor_info::add_in_format(const media_format &in_format) 224 { 225 media_format *p = new(std::nothrow) media_format[in_format_count + 1]; 226 if (p) { 227 for (int i = 0; i < in_format_count; i++) 228 p[i] = in_formats[i]; 229 p[in_format_count] = in_format; 230 delete [] in_formats; 231 in_formats = p; 232 in_format_count += 1; 233 } 234 } 235 236 237 void 238 dormant_flavor_info::add_out_format(const media_format &out_format) 239 { 240 media_format *p = new(std::nothrow) media_format[out_format_count + 1]; 241 if (p) { 242 for (int i = 0; i < out_format_count; i++) 243 p[i] = out_formats[i]; 244 p[out_format_count] = out_format; 245 delete [] out_formats; 246 out_formats = p; 247 out_format_count += 1; 248 } 249 } 250 251 252 bool 253 dormant_flavor_info::IsFixedSize() const 254 { 255 return false; 256 } 257 258 259 type_code 260 dormant_flavor_info::TypeCode() const 261 { 262 return FLATTEN_TYPECODE; 263 } 264 265 266 ssize_t 267 dormant_flavor_info::FlattenedSize() const 268 { 269 ssize_t size = 0; 270 // magic 271 size += sizeof(int32); 272 // size 273 size += sizeof(int32); 274 // struct flavor_info 275 size += sizeof(int32) + strlen(name); 276 size += sizeof(int32) + strlen(info); 277 size += sizeof(kinds); 278 size += sizeof(flavor_flags); 279 size += sizeof(internal_id); 280 size += sizeof(possible_count); 281 size += sizeof(in_format_count); 282 size += sizeof(in_format_flags); 283 if (in_format_count > 0 && in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT 284 && in_formats != NULL) 285 size += in_format_count * sizeof(media_format); 286 size += sizeof(out_format_count); 287 size += sizeof(out_format_flags); 288 if (out_format_count > 0 && out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT 289 && out_formats != NULL) 290 size += out_format_count * sizeof(media_format); 291 // struct dormant_node_info node_info 292 size += sizeof(node_info); 293 294 return size; 295 } 296 297 298 status_t 299 dormant_flavor_info::Flatten(void *buffer, ssize_t size) const 300 { 301 if (size < FlattenedSize()) 302 return B_ERROR; 303 304 char *buf = (char *)buffer; 305 int32 nameLength = name ? (int32)strlen(name) : -1; 306 int32 infoLength = info ? (int32)strlen(info) : -1; 307 int32 inFormatCount = 0; 308 size_t inFormatSize = 0; 309 int32 outFormatCount = 0; 310 size_t outFormatSize = 0; 311 312 if ((kinds & B_BUFFER_CONSUMER) != 0 && in_format_count > 0 313 && in_formats != NULL) { 314 if (in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT) { 315 inFormatCount = in_format_count; 316 inFormatSize = in_format_count * sizeof(media_format); 317 } else { 318 fprintf(stderr, "error dormant_flavor_info::Flatten: " 319 "in_format_count is too large\n"); 320 return B_ERROR; 321 } 322 } 323 324 if ((kinds & B_BUFFER_PRODUCER) != 0 && out_format_count > 0 325 && out_formats != NULL) { 326 if (out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { 327 outFormatCount = out_format_count; 328 outFormatSize = out_format_count * sizeof(media_format); 329 } else { 330 fprintf(stderr, "error dormant_flavor_info::Flatten: " 331 "out_format_count is too large\n"); 332 return B_ERROR; 333 } 334 } 335 336 // magic 337 *(int32*)buf = FLATTEN_MAGIC; buf += sizeof(int32); 338 339 // size 340 *(int32*)buf = FlattenedSize(); buf += sizeof(int32); 341 342 // struct flavor_info 343 *(int32*)buf = nameLength; buf += sizeof(int32); 344 if (nameLength > 0) { 345 memcpy(buf, name, nameLength); 346 buf += nameLength; 347 } 348 *(int32*)buf = infoLength; buf += sizeof(int32); 349 if (infoLength > 0) { 350 memcpy(buf, info, infoLength); 351 buf += infoLength; 352 } 353 354 *(uint64*)buf = kinds; buf += sizeof(uint64); 355 *(uint32*)buf = flavor_flags; buf += sizeof(uint32); 356 *(int32*)buf = internal_id; buf += sizeof(int32); 357 *(int32*)buf = possible_count; buf += sizeof(int32); 358 *(int32*)buf = inFormatCount; buf += sizeof(int32); 359 *(uint32*)buf = in_format_flags; buf += sizeof(uint32); 360 361 // XXX FIXME! we should not!!! make flat copies of media_format 362 memcpy(buf, in_formats, inFormatSize); buf += inFormatSize; 363 364 *(int32*)buf = outFormatCount; buf += sizeof(int32); 365 *(uint32*)buf = out_format_flags; buf += sizeof(uint32); 366 367 // XXX FIXME! we should not!!! make flat copies of media_format 368 memcpy(buf, out_formats, outFormatSize); buf += outFormatSize; 369 370 *(dormant_node_info*)buf = node_info; buf += sizeof(dormant_node_info); 371 372 return B_OK; 373 } 374 375 376 status_t 377 dormant_flavor_info::Unflatten(type_code c, const void *buffer, ssize_t size) 378 { 379 if (c != FLATTEN_TYPECODE) 380 return B_ERROR; 381 if (size < 8) 382 return B_ERROR; 383 384 const char *buf = (const char *)buffer; 385 int32 nameLength; 386 int32 infoLength; 387 388 // check magic 389 if (*(int32*)buf != FLATTEN_MAGIC) 390 return B_ERROR; 391 buf += sizeof(int32); 392 393 // check size 394 if (*(uint32*)buf > (uint32)size) 395 return B_ERROR; 396 buf += sizeof(int32); 397 398 delete[] name; 399 name = NULL; 400 delete[] info; 401 info = NULL; 402 delete[] in_formats; 403 in_formats = NULL; 404 in_format_count = 0; 405 delete[] out_formats; 406 out_formats = NULL; 407 out_format_count = 0; 408 409 // struct flavor_info 410 nameLength = *(int32*)buf; buf += sizeof(int32); 411 if (nameLength >= 0) { // if nameLength is -1, we leave name = 0 412 name = new(std::nothrow) char [nameLength + 1]; 413 if (name) { 414 memcpy(name, buf, nameLength); 415 name[nameLength] = 0; 416 buf += nameLength; // XXX not save 417 } 418 } 419 420 infoLength = *(int32*)buf; buf += sizeof(int32); 421 if (infoLength >= 0) { // if infoLength is -1, we leave info = 0 422 info = new(std::nothrow) char [infoLength + 1]; 423 if (info) { 424 memcpy(info, buf, infoLength); 425 info[infoLength] = 0; 426 buf += infoLength; // XXX not save 427 } 428 } 429 430 int32 count; 431 432 kinds = *(uint64*)buf; buf += sizeof(uint64); 433 flavor_flags = *(uint32*)buf; buf += sizeof(uint32); 434 internal_id = *(int32*)buf; buf += sizeof(int32); 435 possible_count = *(int32*)buf; buf += sizeof(int32); 436 count = *(int32*)buf; buf += sizeof(int32); 437 in_format_flags = *(uint32*)buf; buf += sizeof(uint32); 438 439 if (count > 0) { 440 if (count <= MAX_FLAVOR_IN_FORMAT_COUNT) { 441 in_formats = new(std::nothrow) media_format[count]; 442 if (!in_formats) 443 return B_NO_MEMORY; 444 // TODO: we should not!!! make flat copies of media_format 445 for (int32 i = 0; i < count; i++) { 446 const_cast<media_format*> 447 (&in_formats[i])->Unflatten(buf); 448 buf += sizeof(media_format); // TODO: not save 449 } 450 in_format_count = count; 451 } 452 } 453 454 count = *(int32*)buf; buf += sizeof(int32); 455 out_format_flags = *(uint32*)buf; buf += sizeof(uint32); 456 457 if (count > 0) { 458 if (count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { 459 out_formats = new(std::nothrow) media_format[count]; 460 if (!out_formats) 461 return B_NO_MEMORY; 462 // TODO: we should not!!! make flat copies of media_format 463 for (int32 i = 0; i < count; i++) { 464 const_cast<media_format*> 465 (&out_formats[i])->Unflatten(buf); 466 buf += sizeof(media_format); // TODO: not save 467 } 468 out_format_count = count; 469 } 470 } 471 472 node_info = *(dormant_node_info*)buf; buf += sizeof(dormant_node_info); 473 474 return B_OK; 475 } 476 477 478 // #pragma mark - BMediaAddOn 479 480 481 BMediaAddOn::BMediaAddOn(image_id image) 482 : 483 fImage(image), 484 fAddon(0) 485 { 486 CALLED(); 487 } 488 489 490 BMediaAddOn::~BMediaAddOn() 491 { 492 CALLED(); 493 } 494 495 496 status_t 497 BMediaAddOn::InitCheck(const char **_failureText) 498 { 499 CALLED(); 500 // only to be implemented by derived classes 501 *_failureText = "no error"; 502 return B_OK; 503 } 504 505 506 int32 507 BMediaAddOn::CountFlavors() 508 { 509 CALLED(); 510 // only to be implemented by derived classes 511 return 0; 512 } 513 514 515 status_t 516 BMediaAddOn::GetFlavorAt(int32 n, const flavor_info **_info) 517 { 518 CALLED(); 519 // only to be implemented by derived classes 520 return B_ERROR; 521 } 522 523 524 BMediaNode* 525 BMediaAddOn::InstantiateNodeFor(const flavor_info *info, BMessage *config, 526 status_t *_error) 527 { 528 CALLED(); 529 // only to be implemented by derived classes 530 return NULL; 531 } 532 533 534 status_t 535 BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *toMessage) 536 { 537 CALLED(); 538 // only to be implemented by derived classes 539 return B_ERROR; 540 } 541 542 543 bool 544 BMediaAddOn::WantsAutoStart() 545 { 546 CALLED(); 547 // only to be implemented by derived classes 548 return false; 549 } 550 551 552 status_t 553 BMediaAddOn::AutoStart(int count, BMediaNode **_node, int32 *_internalID, 554 bool *_hasMore) 555 { 556 CALLED(); 557 // only to be implemented by derived classes 558 return B_ERROR; 559 } 560 561 562 status_t 563 BMediaAddOn::SniffRef(const entry_ref &file, BMimeType *mimeType, 564 float *_quality, int32 *_internalID) 565 { 566 CALLED(); 567 // only to be implemented by BFileInterface derived classes 568 return B_ERROR; 569 } 570 571 572 status_t 573 BMediaAddOn::SniffType(const BMimeType &type, float *_quality, 574 int32 *_internalID) 575 { 576 CALLED(); 577 // only to be implemented by BFileInterface derived classes 578 return B_ERROR; 579 } 580 581 582 status_t 583 BMediaAddOn::GetFileFormatList(int32 flavorID, 584 media_file_format *writableFormats, int32 maxWriteItems, int32 *_writeItems, 585 media_file_format *readableFormats, int32 maxReadItems, int32 *_readItems, 586 void *_reserved) 587 { 588 CALLED(); 589 // only to be implemented by BFileInterface derived classes 590 return B_ERROR; 591 } 592 593 594 status_t 595 BMediaAddOn::SniffTypeKind(const BMimeType &type, uint64 kinds, float *_quality, 596 int32 *_internalID, void *_reserved) 597 { 598 CALLED(); 599 // only to be implemented by BFileInterface derived classes 600 return B_ERROR; 601 } 602 603 604 image_id 605 BMediaAddOn::ImageID() 606 { 607 return fImage; 608 } 609 610 611 media_addon_id 612 BMediaAddOn::AddonID() 613 { 614 return fAddon; 615 } 616 617 618 // #pragma mark - protected BMediaAddOn 619 620 621 status_t 622 BMediaAddOn::NotifyFlavorChange() 623 { 624 CALLED(); 625 if (fAddon == 0) 626 return B_ERROR; 627 628 add_on_server_rescan_flavors_command command; 629 command.add_on_id = fAddon; 630 return SendToAddOnServer(ADD_ON_SERVER_RESCAN_ADD_ON_FLAVORS, &command, 631 sizeof(command)); 632 } 633 634 635 // #pragma mark - private BMediaAddOn 636 637 638 /* 639 unimplemented: 640 BMediaAddOn::BMediaAddOn() 641 BMediaAddOn::BMediaAddOn(const BMediaAddOn &clone) 642 BMediaAddOn & BMediaAddOn::operator=(const BMediaAddOn &clone) 643 */ 644 645 646 extern "C" { 647 // declared here to remove them from the class header file 648 status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::GetFileFormatList */ 649 status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::SniffTypeKind */ 650 status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *) { return B_ERROR; } 651 status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *) { return B_ERROR; } 652 }; 653 654 status_t BMediaAddOn::_Reserved_MediaAddOn_2(void *) { return B_ERROR; } 655 status_t BMediaAddOn::_Reserved_MediaAddOn_3(void *) { return B_ERROR; } 656 status_t BMediaAddOn::_Reserved_MediaAddOn_4(void *) { return B_ERROR; } 657 status_t BMediaAddOn::_Reserved_MediaAddOn_5(void *) { return B_ERROR; } 658 status_t BMediaAddOn::_Reserved_MediaAddOn_6(void *) { return B_ERROR; } 659 status_t BMediaAddOn::_Reserved_MediaAddOn_7(void *) { return B_ERROR; } 660 661