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 #include <MediaAddOn.h> 31 #include <string.h> 32 #include <stdlib.h> 33 #include <new> 34 #include "debug.h" 35 #include "DataExchange.h" 36 37 /* 38 * some little helper function 39 */ 40 41 static inline char *_newstrdup(const char *str); 42 char *_newstrdup(const char *str) 43 { 44 if (str == NULL) 45 return NULL; 46 int len = strlen(str) + 1; 47 char *p = new(std::nothrow) char[len]; 48 if (p) 49 memcpy(p, str, len); 50 return p; 51 } 52 53 #define MAX_FLAVOR_IN_FORMAT_COUNT 300 54 #define MAX_FLAVOR_OUT_FORMAT_COUNT 300 55 56 #define FLATTEN_MAGIC 'CODE' 57 #define FLATTEN_TYPECODE 'DFIT' 58 59 /************************************************************* 60 * public dormant_node_info 61 *************************************************************/ 62 63 // final & verified 64 dormant_node_info::dormant_node_info() 65 : addon(-1), 66 flavor_id(-1) 67 { 68 name[0] = '\0'; 69 } 70 71 // final 72 dormant_node_info::~dormant_node_info() 73 { 74 } 75 76 /************************************************************* 77 * private flavor_info 78 *************************************************************/ 79 80 /* DO NOT IMPLEMENT */ 81 /* 82 flavor_info &flavor_info::operator=(const flavor_info &other) 83 */ 84 85 /************************************************************* 86 * public dormant_flavor_info 87 *************************************************************/ 88 89 // final & verified 90 dormant_flavor_info::dormant_flavor_info() 91 { 92 name = 0; 93 info = 0; 94 kinds = 0; 95 flavor_flags = 0; 96 internal_id = 0; 97 possible_count = 0; 98 in_format_count = 0; 99 in_format_flags = 0; 100 in_formats = 0; 101 out_format_count = 0; 102 out_format_flags = 0; 103 out_formats = 0; 104 } 105 106 107 /* virtual */ 108 dormant_flavor_info::~dormant_flavor_info() 109 { 110 delete [] name; 111 delete [] info; 112 delete [] in_formats; 113 delete [] out_formats; 114 } 115 116 117 dormant_flavor_info::dormant_flavor_info(const dormant_flavor_info &clone) 118 { 119 *this = clone; 120 } 121 122 123 dormant_flavor_info & 124 dormant_flavor_info::operator=(const dormant_flavor_info &clone) 125 { 126 // call operator=(const flavor_info &clone) to copy the flavor_info base class 127 *this = static_cast<const flavor_info>(clone); 128 // copy the dormant_node_info member variable 129 node_info = clone.node_info; 130 return *this; 131 } 132 133 134 dormant_flavor_info & 135 dormant_flavor_info::operator=(const flavor_info &clone) 136 { 137 kinds = clone.kinds; 138 flavor_flags = clone.flavor_flags; 139 internal_id = clone.internal_id; 140 possible_count = clone.possible_count; 141 142 delete [] info; 143 info = _newstrdup(clone.info); 144 145 delete [] name; 146 name = _newstrdup(clone.name); 147 148 delete [] in_formats; 149 in_formats = 0; 150 in_format_count = 0; 151 in_format_flags = clone.in_format_flags; 152 if (kinds & B_BUFFER_CONSUMER) { 153 if (clone.in_format_count >= 0 && clone.in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT) { 154 in_formats = new(std::nothrow) media_format[clone.in_format_count]; 155 if (in_formats != NULL && clone.in_formats != NULL) { 156 in_format_count = clone.in_format_count; 157 for (int i = 0; i < in_format_count; i++) 158 const_cast<media_format &>(in_formats[i]) = clone.in_formats[i]; 159 } 160 } else 161 fprintf(stderr, "error: dormant_flavor_info::operator= clone.in_format_count is invalid\n"); 162 } else if (clone.in_format_count) 163 fprintf(stderr, "warning: dormant_flavor_info::operator= not B_BUFFER_CONSUMER and clone.in_format_count is != 0\n"); 164 165 delete [] out_formats; 166 out_formats = 0; 167 out_format_count = 0; 168 out_format_flags = clone.out_format_flags; 169 if (kinds & B_BUFFER_PRODUCER) { 170 if (clone.out_format_count >= 0 && clone.out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { 171 out_formats = new(std::nothrow) media_format[clone.out_format_count]; 172 if (out_formats != NULL && clone.out_formats != NULL) { 173 out_format_count = clone.out_format_count; 174 for (int i = 0; i < out_format_count; i++) 175 const_cast<media_format &>(out_formats[i]) = clone.out_formats[i]; 176 } 177 } else 178 fprintf(stderr, "error dormant_flavor_info::operator= clone.out_format_count is invalid\n"); 179 } else if (clone.out_format_count) 180 fprintf(stderr, "warning: dormant_flavor_info::operator= not B_BUFFER_PRODUCER and clone.out_format_count is != 0\n"); 181 182 // initialize node_info with default values from dormant_node_info constructor 183 dormant_node_info defaultValues; 184 node_info = defaultValues; 185 186 return *this; 187 } 188 189 190 void 191 dormant_flavor_info::set_name(const char *in_name) 192 { 193 delete [] name; 194 name = _newstrdup(in_name); 195 } 196 197 198 void 199 dormant_flavor_info::set_info(const char *in_info) 200 { 201 delete [] info; 202 info = _newstrdup(in_info); 203 } 204 205 206 void 207 dormant_flavor_info::add_in_format(const media_format &in_format) 208 { 209 media_format *p = new(std::nothrow) media_format[in_format_count + 1]; 210 if (p) { 211 for (int i = 0; i < in_format_count; i++) 212 p[i] = in_formats[i]; 213 p[in_format_count] = in_format; 214 delete [] in_formats; 215 in_formats = p; 216 in_format_count += 1; 217 } 218 } 219 220 221 void 222 dormant_flavor_info::add_out_format(const media_format &out_format) 223 { 224 media_format *p = new(std::nothrow) media_format[out_format_count + 1]; 225 if (p) { 226 for (int i = 0; i < out_format_count; i++) 227 p[i] = out_formats[i]; 228 p[out_format_count] = out_format; 229 delete [] out_formats; 230 out_formats = p; 231 out_format_count += 1; 232 } 233 } 234 235 236 /* virtual */ bool 237 dormant_flavor_info::IsFixedSize() const 238 { 239 return false; 240 } 241 242 243 /* virtual */ type_code 244 dormant_flavor_info::TypeCode() const 245 { 246 return FLATTEN_TYPECODE; 247 } 248 249 250 /* virtual */ ssize_t 251 dormant_flavor_info::FlattenedSize() const 252 { 253 ssize_t size = 0; 254 // magic 255 size += sizeof(int32); 256 // size 257 size += sizeof(int32); 258 // struct flavor_info 259 size += sizeof(int32) + strlen(name); 260 size += sizeof(int32) + strlen(info); 261 size += sizeof(kinds); 262 size += sizeof(flavor_flags); 263 size += sizeof(internal_id); 264 size += sizeof(possible_count); 265 size += sizeof(in_format_count); 266 size += sizeof(in_format_flags); 267 if (in_format_count > 0 && in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT && in_formats != NULL) 268 size += in_format_count * sizeof(media_format); 269 size += sizeof(out_format_count); 270 size += sizeof(out_format_flags); 271 if (out_format_count > 0 && out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT && out_formats != NULL) 272 size += out_format_count * sizeof(media_format); 273 // struct dormant_node_info node_info 274 size += sizeof(node_info); 275 276 return size; 277 } 278 279 280 /* virtual */ status_t 281 dormant_flavor_info::Flatten(void *buffer, 282 ssize_t size) const 283 { 284 if (size < FlattenedSize()) 285 return B_ERROR; 286 287 char *buf = (char *)buffer; 288 int32 nameLength = name ? (int32)strlen(name) : -1; 289 int32 infoLength = info ? (int32)strlen(info) : -1; 290 int32 inFormatCount = 0; 291 size_t inFormatSize = 0; 292 int32 outFormatCount = 0; 293 size_t outFormatSize = 0; 294 295 if ((kinds & B_BUFFER_CONSUMER) && in_format_count > 0 && in_formats != NULL) { 296 if (in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT) { 297 inFormatCount = in_format_count; 298 inFormatSize = in_format_count * sizeof(media_format); 299 } else { 300 fprintf(stderr, "error dormant_flavor_info::Flatten: in_format_count is too large\n"); 301 return B_ERROR; 302 } 303 } 304 305 if ((kinds & B_BUFFER_PRODUCER) && out_format_count > 0 && out_formats != NULL) { 306 if (out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { 307 outFormatCount = out_format_count; 308 outFormatSize = out_format_count * sizeof(media_format); 309 } else { 310 fprintf(stderr, "error dormant_flavor_info::Flatten: out_format_count is too large\n"); 311 return B_ERROR; 312 } 313 } 314 315 // magic 316 *(int32*)buf = FLATTEN_MAGIC; buf += sizeof(int32); 317 318 // size 319 *(int32*)buf = FlattenedSize(); buf += sizeof(int32); 320 321 // struct flavor_info 322 *(int32*)buf = nameLength; buf += sizeof(int32); 323 if (nameLength > 0) { 324 memcpy(buf, name, nameLength); 325 buf += nameLength; 326 } 327 *(int32*)buf = infoLength; buf += sizeof(int32); 328 if (infoLength > 0) { 329 memcpy(buf, info, infoLength); 330 buf += infoLength; 331 } 332 333 *(uint64*)buf = kinds; buf += sizeof(uint64); 334 *(uint32*)buf = flavor_flags; buf += sizeof(uint32); 335 *(int32*)buf = internal_id; buf += sizeof(int32); 336 *(int32*)buf = possible_count; buf += sizeof(int32); 337 *(int32*)buf = inFormatCount; buf += sizeof(int32); 338 *(uint32*)buf = in_format_flags; buf += sizeof(uint32); 339 340 // XXX FIXME! we should not!!! make flat copies of media_format 341 memcpy(buf, in_formats, inFormatSize); buf += inFormatSize; 342 343 *(int32*)buf = outFormatCount; buf += sizeof(int32); 344 *(uint32*)buf = out_format_flags; buf += sizeof(uint32); 345 346 // XXX FIXME! we should not!!! make flat copies of media_format 347 memcpy(buf, out_formats, outFormatSize); buf += outFormatSize; 348 349 *(dormant_node_info*)buf = node_info; buf += sizeof(dormant_node_info); 350 351 return B_OK; 352 } 353 354 355 /* virtual */ status_t 356 dormant_flavor_info::Unflatten(type_code c, 357 const void *buffer, 358 ssize_t size) 359 { 360 if (c != FLATTEN_TYPECODE) 361 return B_ERROR; 362 if (size < 8) 363 return B_ERROR; 364 365 const char *buf = (const char *)buffer; 366 int32 nameLength; 367 int32 infoLength; 368 369 // check magic 370 if (*(int32*)buf != FLATTEN_MAGIC) 371 return B_ERROR; 372 buf += sizeof(int32); 373 374 // check size 375 if (*(uint32*)buf > (uint32)size) 376 return B_ERROR; 377 buf += sizeof(int32); 378 379 delete [] name; 380 name = NULL; 381 delete [] info; 382 info = NULL; 383 delete [] in_formats; 384 in_formats = NULL; 385 in_format_count = 0; 386 delete [] out_formats; 387 out_formats = NULL; 388 out_format_count = 0; 389 390 // struct flavor_info 391 nameLength = *(int32*)buf; buf += sizeof(int32); 392 if (nameLength >= 0) { // if nameLength is -1, we leave name = 0 393 name = new(std::nothrow) char [nameLength + 1]; 394 if (name) { 395 memcpy(name, buf, nameLength); 396 name[nameLength] = 0; 397 buf += nameLength; // XXX not save 398 } 399 } 400 401 infoLength = *(int32*)buf; buf += sizeof(int32); 402 if (infoLength >= 0) { // if infoLength is -1, we leave info = 0 403 info = new(std::nothrow) char [infoLength + 1]; 404 if (info) { 405 memcpy(info, buf, infoLength); 406 info[infoLength] = 0; 407 buf += infoLength; // XXX not save 408 } 409 } 410 411 int32 count; 412 413 kinds = *(uint64*)buf; buf += sizeof(uint64); 414 flavor_flags = *(uint32*)buf; buf += sizeof(uint32); 415 internal_id = *(int32*)buf; buf += sizeof(int32); 416 possible_count = *(int32*)buf; buf += sizeof(int32); 417 count = *(int32*)buf; buf += sizeof(int32); 418 in_format_flags = *(uint32*)buf; buf += sizeof(uint32); 419 420 if (count > 0) { 421 if (count <= MAX_FLAVOR_IN_FORMAT_COUNT) { 422 in_formats = new(std::nothrow) media_format[count]; 423 if (!in_formats) 424 return B_NO_MEMORY; 425 // XXX FIXME! we should not!!! make flat copies of media_format 426 memcpy(const_cast<media_format *>(in_formats), buf, count * sizeof(media_format)); 427 in_format_count = count; 428 } 429 buf += count * sizeof(media_format); // XXX not save 430 } 431 432 count = *(int32*)buf; buf += sizeof(int32); 433 out_format_flags = *(uint32*)buf; buf += sizeof(uint32); 434 435 if (count > 0) { 436 if (count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { 437 out_formats = new(std::nothrow) media_format[count]; 438 if (!out_formats) 439 return B_NO_MEMORY; 440 // XXX FIXME! we should not!!! make flat copies of media_format 441 memcpy(const_cast<media_format *>(out_formats), buf, count * sizeof(media_format)); 442 out_format_count = count; 443 } 444 buf += count * sizeof(media_format); // XXX not save 445 } 446 447 node_info = *(dormant_node_info*)buf; buf += sizeof(dormant_node_info); 448 449 return B_OK; 450 } 451 452 /************************************************************* 453 * public BMediaAddOn 454 *************************************************************/ 455 456 /* explicit */ 457 BMediaAddOn::BMediaAddOn(image_id image) : 458 fImage(image), 459 fAddon(0) 460 { 461 CALLED(); 462 } 463 464 465 /* virtual */ 466 BMediaAddOn::~BMediaAddOn() 467 { 468 CALLED(); 469 } 470 471 472 /* virtual */ status_t 473 BMediaAddOn::InitCheck(const char **out_failure_text) 474 { 475 CALLED(); 476 // only to be implemented by derived classes 477 *out_failure_text = "no error"; 478 return B_OK; 479 } 480 481 482 /* virtual */ int32 483 BMediaAddOn::CountFlavors() 484 { 485 CALLED(); 486 // only to be implemented by derived classes 487 return 0; 488 } 489 490 491 /* virtual */ status_t 492 BMediaAddOn::GetFlavorAt(int32 n, 493 const flavor_info **out_info) 494 { 495 CALLED(); 496 // only to be implemented by derived classes 497 return B_ERROR; 498 } 499 500 501 /* virtual */ BMediaNode * 502 BMediaAddOn::InstantiateNodeFor(const flavor_info *info, 503 BMessage *config, 504 status_t *out_error) 505 { 506 CALLED(); 507 // only to be implemented by derived classes 508 return NULL; 509 } 510 511 512 /* virtual */ status_t 513 BMediaAddOn::GetConfigurationFor(BMediaNode *your_node, 514 BMessage *into_message) 515 { 516 CALLED(); 517 // only to be implemented by derived classes 518 return B_ERROR; 519 } 520 521 522 /* virtual */ bool 523 BMediaAddOn::WantsAutoStart() 524 { 525 CALLED(); 526 // only to be implemented by derived classes 527 return false; 528 } 529 530 531 /* virtual */ status_t 532 BMediaAddOn::AutoStart(int in_count, 533 BMediaNode **out_node, 534 int32 *out_internal_id, 535 bool *out_has_more) 536 { 537 CALLED(); 538 // only to be implemented by derived classes 539 return B_ERROR; 540 } 541 542 543 /* virtual */ status_t 544 BMediaAddOn::SniffRef(const entry_ref &file, 545 BMimeType *io_mime_type, 546 float *out_quality, 547 int32 *out_internal_id) 548 { 549 CALLED(); 550 // only to be implemented by BFileInterface derived classes 551 return B_ERROR; 552 } 553 554 555 /* virtual */ status_t 556 BMediaAddOn::SniffType(const BMimeType &type, 557 float *out_quality, 558 int32 *out_internal_id) 559 { 560 CALLED(); 561 // only to be implemented by BFileInterface derived classes 562 return B_ERROR; 563 } 564 565 566 /* virtual */ status_t 567 BMediaAddOn::GetFileFormatList(int32 flavor_id, 568 media_file_format *out_writable_formats, 569 int32 in_write_items, 570 int32 *out_write_items, 571 media_file_format *out_readable_formats, 572 int32 in_read_items, 573 int32 *out_read_items, 574 void *_reserved) 575 { 576 CALLED(); 577 // only to be implemented by BFileInterface derived classes 578 return B_ERROR; 579 } 580 581 582 /* virtual */ status_t 583 BMediaAddOn::SniffTypeKind(const BMimeType &type, 584 uint64 in_kinds, 585 float *out_quality, 586 int32 *out_internal_id, 587 void *_reserved) 588 { 589 CALLED(); 590 // only to be implemented by BFileInterface derived classes 591 return B_ERROR; 592 } 593 594 595 image_id 596 BMediaAddOn::ImageID() 597 { 598 return fImage; 599 } 600 601 602 media_addon_id 603 BMediaAddOn::AddonID() 604 { 605 return fAddon; 606 } 607 608 /************************************************************* 609 * protected BMediaAddOn 610 *************************************************************/ 611 612 status_t 613 BMediaAddOn::NotifyFlavorChange() 614 { 615 CALLED(); 616 if (fAddon == 0) 617 return B_ERROR; 618 619 addonserver_rescan_mediaaddon_flavors_command command; 620 command.addonid = fAddon; 621 return SendToAddonServer(ADDONSERVER_RESCAN_MEDIAADDON_FLAVORS, &command, sizeof(command)); 622 } 623 624 /************************************************************* 625 * private BMediaAddOn 626 *************************************************************/ 627 628 /* 629 unimplemented: 630 BMediaAddOn::BMediaAddOn() 631 BMediaAddOn::BMediaAddOn(const BMediaAddOn &clone) 632 BMediaAddOn & BMediaAddOn::operator=(const BMediaAddOn &clone) 633 */ 634 635 636 /************************************************************* 637 * private BMediaAddOn 638 *************************************************************/ 639 640 extern "C" { 641 // declared here to remove them from the class header file 642 status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::GetFileFormatList */ 643 status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::SniffTypeKind */ 644 status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *) { return B_ERROR; } 645 status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *) { return B_ERROR; } 646 }; 647 648 status_t BMediaAddOn::_Reserved_MediaAddOn_2(void *) { return B_ERROR; } 649 status_t BMediaAddOn::_Reserved_MediaAddOn_3(void *) { return B_ERROR; } 650 status_t BMediaAddOn::_Reserved_MediaAddOn_4(void *) { return B_ERROR; } 651 status_t BMediaAddOn::_Reserved_MediaAddOn_5(void *) { return B_ERROR; } 652 status_t BMediaAddOn::_Reserved_MediaAddOn_6(void *) { return B_ERROR; } 653 status_t BMediaAddOn::_Reserved_MediaAddOn_7(void *) { return B_ERROR; } 654 655