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 "debug.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 memcpy(const_cast<media_format *>(in_formats), buf, 446 count * sizeof(media_format)); 447 in_format_count = count; 448 } 449 buf += count * sizeof(media_format); // TODO: not save 450 } 451 452 count = *(int32*)buf; buf += sizeof(int32); 453 out_format_flags = *(uint32*)buf; buf += sizeof(uint32); 454 455 if (count > 0) { 456 if (count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { 457 out_formats = new(std::nothrow) media_format[count]; 458 if (!out_formats) 459 return B_NO_MEMORY; 460 // TODO: we should not!!! make flat copies of media_format 461 memcpy(const_cast<media_format *>(out_formats), buf, 462 count * sizeof(media_format)); 463 out_format_count = count; 464 } 465 buf += count * sizeof(media_format); // TODO: not save 466 } 467 468 node_info = *(dormant_node_info*)buf; buf += sizeof(dormant_node_info); 469 470 return B_OK; 471 } 472 473 474 // #pragma mark - BMediaAddOn 475 476 477 BMediaAddOn::BMediaAddOn(image_id image) 478 : 479 fImage(image), 480 fAddon(0) 481 { 482 CALLED(); 483 } 484 485 486 BMediaAddOn::~BMediaAddOn() 487 { 488 CALLED(); 489 } 490 491 492 status_t 493 BMediaAddOn::InitCheck(const char **_failureText) 494 { 495 CALLED(); 496 // only to be implemented by derived classes 497 *_failureText = "no error"; 498 return B_OK; 499 } 500 501 502 int32 503 BMediaAddOn::CountFlavors() 504 { 505 CALLED(); 506 // only to be implemented by derived classes 507 return 0; 508 } 509 510 511 status_t 512 BMediaAddOn::GetFlavorAt(int32 n, const flavor_info **_info) 513 { 514 CALLED(); 515 // only to be implemented by derived classes 516 return B_ERROR; 517 } 518 519 520 BMediaNode* 521 BMediaAddOn::InstantiateNodeFor(const flavor_info *info, BMessage *config, 522 status_t *_error) 523 { 524 CALLED(); 525 // only to be implemented by derived classes 526 return NULL; 527 } 528 529 530 status_t 531 BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *toMessage) 532 { 533 CALLED(); 534 // only to be implemented by derived classes 535 return B_ERROR; 536 } 537 538 539 bool 540 BMediaAddOn::WantsAutoStart() 541 { 542 CALLED(); 543 // only to be implemented by derived classes 544 return false; 545 } 546 547 548 status_t 549 BMediaAddOn::AutoStart(int count, BMediaNode **_node, int32 *_internalID, 550 bool *_hasMore) 551 { 552 CALLED(); 553 // only to be implemented by derived classes 554 return B_ERROR; 555 } 556 557 558 status_t 559 BMediaAddOn::SniffRef(const entry_ref &file, BMimeType *mimeType, 560 float *_quality, int32 *_internalID) 561 { 562 CALLED(); 563 // only to be implemented by BFileInterface derived classes 564 return B_ERROR; 565 } 566 567 568 status_t 569 BMediaAddOn::SniffType(const BMimeType &type, float *_quality, 570 int32 *_internalID) 571 { 572 CALLED(); 573 // only to be implemented by BFileInterface derived classes 574 return B_ERROR; 575 } 576 577 578 status_t 579 BMediaAddOn::GetFileFormatList(int32 flavorID, 580 media_file_format *writableFormats, int32 maxWriteItems, int32 *_writeItems, 581 media_file_format *readableFormats, int32 maxReadItems, int32 *_readItems, 582 void *_reserved) 583 { 584 CALLED(); 585 // only to be implemented by BFileInterface derived classes 586 return B_ERROR; 587 } 588 589 590 status_t 591 BMediaAddOn::SniffTypeKind(const BMimeType &type, uint64 kinds, float *_quality, 592 int32 *_internalID, void *_reserved) 593 { 594 CALLED(); 595 // only to be implemented by BFileInterface derived classes 596 return B_ERROR; 597 } 598 599 600 image_id 601 BMediaAddOn::ImageID() 602 { 603 return fImage; 604 } 605 606 607 media_addon_id 608 BMediaAddOn::AddonID() 609 { 610 return fAddon; 611 } 612 613 614 // #pragma mark - protected BMediaAddOn 615 616 617 status_t 618 BMediaAddOn::NotifyFlavorChange() 619 { 620 CALLED(); 621 if (fAddon == 0) 622 return B_ERROR; 623 624 add_on_server_rescan_flavors_command command; 625 command.add_on_id = fAddon; 626 return SendToAddOnServer(ADD_ON_SERVER_RESCAN_ADD_ON_FLAVORS, &command, 627 sizeof(command)); 628 } 629 630 631 // #pragma mark - private BMediaAddOn 632 633 634 /* 635 unimplemented: 636 BMediaAddOn::BMediaAddOn() 637 BMediaAddOn::BMediaAddOn(const BMediaAddOn &clone) 638 BMediaAddOn & BMediaAddOn::operator=(const BMediaAddOn &clone) 639 */ 640 641 642 extern "C" { 643 // declared here to remove them from the class header file 644 status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::GetFileFormatList */ 645 status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::SniffTypeKind */ 646 status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *) { return B_ERROR; } 647 status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *) { return B_ERROR; } 648 }; 649 650 status_t BMediaAddOn::_Reserved_MediaAddOn_2(void *) { return B_ERROR; } 651 status_t BMediaAddOn::_Reserved_MediaAddOn_3(void *) { return B_ERROR; } 652 status_t BMediaAddOn::_Reserved_MediaAddOn_4(void *) { return B_ERROR; } 653 status_t BMediaAddOn::_Reserved_MediaAddOn_5(void *) { return B_ERROR; } 654 status_t BMediaAddOn::_Reserved_MediaAddOn_6(void *) { return B_ERROR; } 655 status_t BMediaAddOn::_Reserved_MediaAddOn_7(void *) { return B_ERROR; } 656 657