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