1 /*****************************************************************************/ 2 // File: TranslatorRoster.cpp 3 // Class: BTranslatorRoster 4 // Reimplemented by: Michael Wilber, Translation Kit Team 5 // Reimplementation: 2002-06-11 6 // 7 // Description: This class is the guts of the translation kit, it makes the 8 // whole thing happen. It bridges the applications using this 9 // object with the translators that the apps need to access. 10 // 11 // 12 // Copyright (c) 2002 OpenBeOS Project 13 // 14 // Original Version: Copyright 1998, Be Incorporated, All Rights Reserved. 15 // Copyright 1995-1997, Jon Watte 16 // 17 // Permission is hereby granted, free of charge, to any person obtaining a 18 // copy of this software and associated documentation files (the "Software"), 19 // to deal in the Software without restriction, including without limitation 20 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 21 // and/or sell copies of the Software, and to permit persons to whom the 22 // Software is furnished to do so, subject to the following conditions: 23 // 24 // The above copyright notice and this permission notice shall be included 25 // in all copies or substantial portions of the Software. 26 // 27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 28 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 32 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 33 // DEALINGS IN THE SOFTWARE. 34 /*****************************************************************************/ 35 36 #include <TranslatorRoster.h> 37 38 // Initialize static member variable 39 BTranslatorRoster *BTranslatorRoster::fspDefaultTranslators = NULL; 40 41 // Extensions used in the extension BMessage, defined in TranslatorFormats.h 42 char B_TRANSLATOR_EXT_HEADER_ONLY[] = "/headerOnly"; 43 char B_TRANSLATOR_EXT_DATA_ONLY[] = "/dataOnly"; 44 char B_TRANSLATOR_EXT_COMMENT[] = "/comment"; 45 char B_TRANSLATOR_EXT_TIME[] = "/time"; 46 char B_TRANSLATOR_EXT_FRAME[] = "/frame"; 47 char B_TRANSLATOR_EXT_BITMAP_RECT[] = "bits/Rect"; 48 char B_TRANSLATOR_EXT_BITMAP_COLOR_SPACE[] = "bits/space"; 49 char B_TRANSLATOR_EXT_BITMAP_PALETTE[] = "bits/palette"; 50 char B_TRANSLATOR_EXT_SOUND_CHANNEL[] = "nois/channel"; 51 char B_TRANSLATOR_EXT_SOUND_MONO[] = "nois/mono"; 52 char B_TRANSLATOR_EXT_SOUND_MARKER[] = "nois/marker"; 53 char B_TRANSLATOR_EXT_SOUND_LOOP[] = "nois/loop"; 54 55 // --------------------------------------------------------------- 56 // Constructor 57 // 58 // Private, unimplimented constructor that no one should use. 59 // I don't think there would be much of a need for this function. 60 // 61 // Preconditions: 62 // 63 // Parameters: tr, not used 64 // 65 // Postconditions: 66 // 67 // Returns: 68 // --------------------------------------------------------------- 69 BTranslatorRoster::BTranslatorRoster(const BTranslatorRoster &tr) 70 : BArchivable() 71 { 72 Initialize(); 73 } 74 75 // --------------------------------------------------------------- 76 // operator= 77 // 78 // Private, unimplimented function that no one should use. 79 // I don't know that there is a need for this function anyway. 80 // 81 // Preconditions: 82 // 83 // Parameters: tr, not used 84 // 85 // Postconditions: 86 // 87 // Returns: refernce to this object 88 // --------------------------------------------------------------- 89 BTranslatorRoster & 90 BTranslatorRoster::operator=(const BTranslatorRoster &tr) 91 { 92 return *this; 93 } 94 95 // --------------------------------------------------------------- 96 // Constructor 97 // 98 // Initilizes the BTranslatorRoster to the empty state, it loads 99 // no translators. 100 // 101 // Preconditions: 102 // 103 // Parameters: 104 // 105 // Postconditions: 106 // 107 // Returns: 108 // --------------------------------------------------------------- 109 BTranslatorRoster::BTranslatorRoster() : BArchivable() 110 { 111 Initialize(); 112 } 113 114 // --------------------------------------------------------------- 115 // Constructor 116 // 117 // This constructor initilizes the BTranslatorRoster, then 118 // loads all of the translators specified in the 119 // "be:translator_path" field of the supplied BMessage. 120 // 121 // Preconditions: 122 // 123 // Parameters: model, the BMessage where the translator paths are 124 // found. 125 // 126 // Postconditions: 127 // 128 // Returns: 129 // --------------------------------------------------------------- 130 BTranslatorRoster::BTranslatorRoster(BMessage *model) : BArchivable() 131 { 132 Initialize(); 133 134 if (model) { 135 BString bstr; 136 for (int32 i = 0; 137 model->FindString("be:translator_path", i, &bstr) == B_OK; i++) { 138 AddTranslators(bstr.String()); 139 bstr = ""; 140 } 141 } 142 } 143 144 // --------------------------------------------------------------- 145 // Initialize() 146 // 147 // This function initializes this object to the empty state. It 148 // is used by all constructors. 149 // 150 // Preconditions: Object must be in initial uninitialized state 151 // 152 // Parameters: 153 // 154 // Postconditions: 155 // 156 // Returns: 157 // --------------------------------------------------------------- 158 void BTranslatorRoster::Initialize() 159 { 160 fpTranslators = fpLastTranslator = NULL; 161 fSem = create_sem(1, "BTranslatorRoster Lock"); 162 } 163 164 // --------------------------------------------------------------- 165 // Destructor 166 // 167 // Unloads any translators that were loaded and frees all memory 168 // allocated by the BTranslatorRoster, except for the static 169 // member data. 170 // 171 // Preconditions: 172 // 173 // Parameters: 174 // 175 // Postconditions: 176 // 177 // Returns: 178 // --------------------------------------------------------------- 179 BTranslatorRoster::~BTranslatorRoster() 180 { 181 if (fSem > 0 && acquire_sem(fSem) == B_NO_ERROR) { 182 183 // If the default BTranslatorRoster is being 184 // deleted, set the pointer to the default 185 // BTranslatorRoster to NULL 186 if (fspDefaultTranslators == this) 187 fspDefaultTranslators = NULL; 188 189 // FIRST PASS: release BTranslator objects 190 translator_node *pTranNode = fpTranslators; 191 while (pTranNode) { 192 translator_node *pRelTranNode = pTranNode; 193 pTranNode = pTranNode->next; 194 pRelTranNode->translator->Release(); 195 } 196 197 // SECOND PASS: unload images and delete nodes 198 // (I can't delete a BTranslator if I've deleted 199 // the code for it) 200 pTranNode = fpTranslators; 201 while (pTranNode) { 202 translator_node *pDelTranNode = pTranNode; 203 pTranNode = pTranNode->next; 204 205 // only try to unload actual images 206 if (pDelTranNode->image >= 0) 207 unload_add_on(pDelTranNode->image); 208 // I may end up trying to unload the same image 209 // more than once, but I don't think 210 // that should be a problem 211 delete[] pDelTranNode->path; 212 delete pDelTranNode; 213 } 214 215 fpTranslators = fpLastTranslator = NULL; 216 } 217 218 delete_sem(fSem); 219 } 220 221 // --------------------------------------------------------------- 222 // Archive 223 // 224 // Archives the BTranslatorRoster by recording its loaded add-ons 225 // in the BMessage into. The deep variable appeared to have no 226 // impact in Be's version of this function, so I went the same 227 // route. 228 // 229 // Preconditions: 230 // 231 // Parameters: into, the BMessage that this object is written to 232 // deep, if true, more data is written, if false, 233 // less data is written 234 // 235 // Postconditions: 236 // 237 // Returns: B_OK, if everything went well 238 // B_BAD_VALUE, if into is NULL 239 // B_NOT_INITIALIZED, if the constructor couldn't create 240 // a semaphore 241 // other errors that BMessage::AddString() and 242 // BArchivable::Archive() return 243 // --------------------------------------------------------------- 244 status_t 245 BTranslatorRoster::Archive(BMessage *into, bool deep) const 246 { 247 if (!into) 248 return B_BAD_VALUE; 249 250 status_t result = B_NOT_INITIALIZED; 251 252 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 253 result = BArchivable::Archive(into, deep); 254 if (result == B_OK) { 255 result = into->AddString("class", "BTranslatorRoster"); 256 257 translator_node *pTranNode = NULL; 258 for (pTranNode = fpTranslators; result == B_OK && pTranNode; 259 pTranNode = pTranNode->next) { 260 if (pTranNode->path[0]) 261 result = into->AddString("be:translator_path", 262 pTranNode->path); 263 } 264 } 265 release_sem(fSem); 266 } 267 268 return result; 269 } 270 271 // --------------------------------------------------------------- 272 // Instantiate 273 // 274 // This static member function returns a new BTranslatorRosters 275 // object, allocated by new and created with the version of the 276 // constructor that takes a BMessage archive. However if the 277 // archive doesn't contain data for a BTranslatorRoster object, 278 // Instantiate() returns NULL. 279 // 280 // Preconditions: 281 // 282 // Parameters: from, the BMessage to create the new object from 283 // 284 // Postconditions: 285 // 286 // Returns: returns NULL if the BMessage was no good 287 // returns a BArchivable * to a BTranslatorRoster 288 // --------------------------------------------------------------- 289 BArchivable * 290 BTranslatorRoster::Instantiate(BMessage *from) 291 { 292 if (!from || !validate_instantiation(from, "BTranslatorRoster")) 293 return NULL; 294 else 295 return new BTranslatorRoster(from); 296 } 297 298 // --------------------------------------------------------------- 299 // Version 300 // 301 // Sets outCurVersion to the Translation Kit protocol version 302 // number and outMinVersion to the minimum protocol version number 303 // supported. Returns a string containing verbose version 304 // information. Currently, inAppVersion must be 305 // B_TRANSLATION_CURRENT_VERSION, but as far as I can tell, its 306 // completely ignored. 307 // 308 // Preconditions: 309 // 310 // Parameters: outCurVersion, the current version is stored here 311 // outMinVersion, the minimum supported version is 312 // stored here 313 // inAppVersion, is ignored as far as I know 314 // 315 // Postconditions: 316 // 317 // Returns: string of verbose translation kit version 318 // information or an empty string if either of the 319 // out variables is NULL. 320 // --------------------------------------------------------------- 321 const char * 322 BTranslatorRoster::Version(int32 *outCurVersion, int32 *outMinVersion, 323 int32 inAppVersion) 324 { 325 if (!outCurVersion || !outMinVersion) 326 return ""; 327 328 static char vString[50]; 329 static char vDate[] = __DATE__; 330 if (!vString[0]) { 331 sprintf(vString, "Translation Kit v%d.%d.%d %s\n", 332 static_cast<int>(B_TRANSLATION_MAJOR_VER(B_TRANSLATION_CURRENT_VERSION)), 333 static_cast<int>(B_TRANSLATION_MINOR_VER(B_TRANSLATION_CURRENT_VERSION)), 334 static_cast<int>(B_TRANSLATION_REVSN_VER(B_TRANSLATION_CURRENT_VERSION)), 335 vDate); 336 } 337 *outCurVersion = B_TRANSLATION_CURRENT_VERSION; 338 *outMinVersion = B_TRANSLATION_MIN_VERSION; 339 return vString; 340 } 341 342 // --------------------------------------------------------------- 343 // Default 344 // 345 // This static member function returns a pointer to the default 346 // BTranslatorRoster that has the default translators stored in 347 // it. The paths for the default translators are loaded from 348 // the TRANSLATORS environment variable. If it does not exist, 349 // the paths used are /boot/home/config/add-ons/Translators, 350 // /boot/home/config/add-ons/Datatypes, and 351 // /system/add-ons/Translators. The BTranslatorRoster returned 352 // by this function is global to the application and should 353 // not be deleted. 354 // 355 // This code probably isn't thread safe (yet). 356 // 357 // Preconditions: 358 // 359 // Parameters: 360 // 361 // Postconditions: 362 // 363 // Returns: pointer to the default BTranslatorRoster 364 // --------------------------------------------------------------- 365 BTranslatorRoster * 366 BTranslatorRoster::Default() 367 { 368 // If the default translators have not been loaded, 369 // create a new BTranslatorRoster for them, and load them. 370 if (!fspDefaultTranslators) { 371 fspDefaultTranslators = new BTranslatorRoster(); 372 fspDefaultTranslators->AddTranslators(NULL); 373 } 374 375 return fspDefaultTranslators; 376 } 377 378 // --------------------------------------------------------------- 379 // AddTranslators 380 // 381 // This function takes a string of colon delimited paths, 382 // (folders or specific files) and adds the translators from 383 // those paths to this BTranslatorRoster. 384 // 385 // If load_path is NULL, it parses the environment variable 386 // TRANSLATORS. If that does not exist, it uses the paths: 387 // /boot/home/config/add-ons/Translators, 388 // /boot/home/config/add-ons/Datatypes and 389 // /system/add-ons/Translators. 390 // 391 // Preconditions: 392 // 393 // Parameters: load_path, colon delimited list of paths 394 // to load translators from 395 // 396 // Postconditions: 397 // 398 // Returns: B_OK on success, 399 // B_BAD_VALUE if there was something wrong with 400 // load_path 401 // other errors for problems with loading add-ons 402 // --------------------------------------------------------------- 403 status_t 404 BTranslatorRoster::AddTranslators(const char *load_path) 405 { 406 if (fSem <= 0) 407 return fSem; 408 409 status_t loadErr = B_ERROR; 410 int32 nLoaded = 0; 411 412 if (acquire_sem(fSem) == B_OK) { 413 if (load_path == NULL) 414 load_path = getenv("TRANSLATORS"); 415 if (load_path == NULL) 416 load_path = kgDefaultTranslatorPath; 417 418 char pathbuf[PATH_MAX]; 419 const char *ptr = load_path; 420 const char *end = ptr; 421 struct stat stbuf; 422 while (*ptr != 0) { 423 // find segments specified by colons 424 end = strchr(ptr, ':'); 425 if (end == NULL) 426 end = ptr + strlen(ptr); 427 if (end-ptr > PATH_MAX - 1) 428 loadErr = B_BAD_VALUE; 429 else { 430 // copy this segment of the path into a path, and load it 431 memcpy(pathbuf, ptr, end - ptr); 432 pathbuf[end - ptr] = 0; 433 434 if (!stat(pathbuf, &stbuf)) { 435 // files are loaded as translators 436 if (S_ISREG(stbuf.st_mode)) { 437 status_t err = LoadTranslator(pathbuf); 438 if (err != B_OK) 439 loadErr = err; 440 else 441 nLoaded++; 442 } else 443 // directories are scanned 444 LoadDir(pathbuf, loadErr, nLoaded); 445 } 446 } 447 ptr = end + 1; 448 if (*end == 0) 449 break; 450 } // while (*ptr != 0) 451 452 release_sem(fSem); 453 454 } // if (acquire_sem(fSem) == B_OK) 455 456 // if anything loaded, it's not too bad 457 if (nLoaded) 458 loadErr = B_OK; 459 460 return loadErr; 461 } 462 463 // --------------------------------------------------------------- 464 // AddTranslator 465 // 466 // Adds a BTranslator based object to the BTranslatorRoster. 467 // When you add a BTranslator roster, it is Acquire()'d by 468 // BTranslatorRoster; it is Release()'d when the 469 // BTranslatorRoster is deleted. 470 // 471 // Preconditions: 472 // 473 // Parameters: translator, the translator to be added to the 474 // BTranslatorRoster 475 // 476 // Postconditions: 477 // 478 // Returns: B_BAD_VALUE, if translator is NULL, 479 // B_NOT_INITIALIZED, if the constructor couldn't 480 // create a semaphore 481 // B_OK if all went well 482 // --------------------------------------------------------------- 483 status_t 484 BTranslatorRoster::AddTranslator(BTranslator *translator) 485 { 486 if (!translator) 487 return B_BAD_VALUE; 488 489 status_t result = B_NOT_INITIALIZED; 490 491 if (fSem > 0 && acquire_sem(fSem) == B_NO_ERROR) { 492 // Add the translator to the list even if 493 // it is already in the list 494 result = AddTranslatorToList(translator); 495 release_sem(fSem); 496 } 497 498 return result; 499 } 500 501 // --------------------------------------------------------------- 502 // Identify 503 // 504 // This function determines which translator is best suited 505 // to convert the data from inSource. 506 // 507 // Preconditions: 508 // 509 // Parameters: inSource, the data to be translated, 510 // ioExtension, the configuration data for the 511 // translator 512 // outInfo, the information about the chosen 513 // translator is put here 514 // inHintType, a hint about the type of data 515 // that is in inSource, can be 516 // zero if type is not known 517 // inHintMIME, a hint about the MIME type of 518 // data that is in inSource, 519 // can be NULL 520 // inWantType, the desired output type for 521 // inSource, if zero, any type 522 // is ok. 523 // 524 // Postconditions: 525 // 526 // Returns: B_OK, identification of inSource was successful, 527 // B_NO_TRANSLATOR, no appropriate translator found 528 // B_NOT_INITIALIZED, the constructor failed to 529 // create a semaphore 530 // B_BAD_VALUE, inSource or outInfo is NULL 531 // other values, error using inSource 532 // --------------------------------------------------------------- 533 status_t 534 BTranslatorRoster::Identify(BPositionIO *inSource, 535 BMessage *ioExtension, translator_info *outInfo, 536 uint32 inHintType, const char *inHintMIME, 537 uint32 inWantType) 538 { 539 if (!inSource || !outInfo) 540 return B_BAD_VALUE; 541 542 status_t result = B_NOT_INITIALIZED; 543 bool bFoundMatch = false; 544 545 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 546 547 translator_node *pTranNode = fpTranslators; 548 float bestWeight = 0.0; 549 for (; pTranNode; pTranNode = pTranNode->next) { 550 551 const translation_format *format = NULL; 552 translator_info tmpInfo; 553 float weight = 0.0; 554 bool addmatch = false; 555 // eliminates need for a goto 556 557 result = inSource->Seek(0, SEEK_SET); 558 if (result == B_OK) { 559 560 int32 inputFormatsCount = 0; 561 const translation_format *inputFormats = 562 pTranNode->translator->InputFormats(&inputFormatsCount); 563 564 if (CheckFormats(inputFormats, inputFormatsCount, inHintType, 565 inHintMIME, &format)) { 566 567 // after checking the formats for hints, we still need to make 568 // sure the translator recognizes the data and can output the 569 // desired format, so we call its' Identify() function. 570 if (format && !pTranNode->translator->Identify(inSource, 571 format, ioExtension, &tmpInfo, inWantType)) 572 addmatch = true; 573 574 } else if (!pTranNode->translator->Identify(inSource, NULL, 575 ioExtension, &tmpInfo, inWantType)) 576 addmatch = true; 577 578 if (addmatch) { 579 weight = tmpInfo.quality * tmpInfo.capability; 580 if (weight > bestWeight) { 581 bFoundMatch = true; 582 bestWeight = weight; 583 584 tmpInfo.translator = pTranNode->id; 585 outInfo->type = tmpInfo.type; 586 outInfo->translator = tmpInfo.translator; 587 outInfo->group = tmpInfo.group; 588 outInfo->quality = tmpInfo.quality; 589 outInfo->capability = tmpInfo.capability; 590 strcpy(outInfo->name, tmpInfo.name); 591 strcpy(outInfo->MIME, tmpInfo.MIME); 592 } 593 } 594 } // if (result == B_OK) 595 } // for (; pTranNode; pTranNode = pTranNode->next) 596 597 if (bFoundMatch) 598 result = B_NO_ERROR; 599 else if (result == B_OK) 600 result = B_NO_TRANSLATOR; 601 602 release_sem(fSem); 603 } // if (acquire_sem(fSem) == B_OK) 604 605 return result; 606 } 607 608 // --------------------------------------------------------------- 609 // compare_data 610 // 611 // This function is not a member of BTranslatorRoster, but it is 612 // used by the GetTranslators() member function as the function 613 // passed to qsort to sort the translators from best to worst. 614 // 615 // Preconditions: 616 // 617 // Parameters: a, pointer to translator_info structure to be 618 // compared to b 619 // b, pointer to translator_info structure to be 620 // compared to a 621 // 622 // Postconditions: 623 // 624 // Returns: 625 // NOTE: Since qsort sorts lowest to highest, and I want 626 // the highest quality/capability first, I must do things 627 // "backwards." 628 // 629 // 0 if A and B are equally capable 630 // -1 if A is more capable than B 631 // 1 if A is less capable than B 632 // --------------------------------------------------------------- 633 static int 634 compare_data(const void *a, const void *b) 635 { 636 register const translator_info *ai = 637 reinterpret_cast<const translator_info *> (a); 638 639 register const translator_info *bi = 640 reinterpret_cast<const translator_info *> (b); 641 642 float acmp, bcmp; 643 acmp = ai->quality * ai->capability; 644 bcmp = bi->quality * bi->capability; 645 if (acmp == bcmp) 646 return 0; 647 else if (acmp > bcmp) 648 return -1; 649 else 650 return 1; 651 } 652 653 // --------------------------------------------------------------- 654 // GetTranslators 655 // 656 // Finds all translators capable of handling the data in inSource 657 // and puts them into the outInfo array (which you must delete 658 // yourself when you are done with it). Specifying a value for 659 // inHintType, inHintMIME and/or inWantType causes only the 660 // translators that satisfy them to be included in the outInfo. 661 // 662 // Preconditions: 663 // 664 // Parameters: inSource, the data that wants to be translated 665 // ioExtension, configuration data for the translator 666 // outInfo, the array of acceptable translators is 667 // stored here if the function succeeds 668 // outNumInfo, number of entries in outInfo 669 // inHintType, hint for the type of data in 670 // inSource, can be zero if the 671 // type is not known 672 // inHintMIME, hint MIME type of the data 673 // in inSource, can be NULL if 674 // the MIME type is not known 675 // inWantType, the desired output type for 676 // the data in inSource, can be zero 677 // for any type. 678 // 679 // Postconditions: 680 // 681 // Returns: B_OK, successfully indentified the data in inSource 682 // B_NO_TRANSLATOR, no translator could handle inSource 683 // B_NOT_INITIALIZED, the constructore failed to create 684 // a semaphore 685 // B_BAD_VALUE, inSource, outInfo, or outNumInfo is NULL 686 // other errors, problems using inSource 687 // --------------------------------------------------------------- 688 status_t 689 BTranslatorRoster::GetTranslators(BPositionIO *inSource, 690 BMessage *ioExtension, translator_info **outInfo, 691 int32 *outNumInfo, uint32 inHintType, 692 const char *inHintMIME, uint32 inWantType) 693 { 694 if (!inSource || !outInfo || !outNumInfo) 695 return B_BAD_VALUE; 696 697 status_t result = B_NOT_INITIALIZED; 698 699 *outInfo = NULL; 700 *outNumInfo = 0; 701 702 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 703 704 int32 physCnt = 10; 705 *outInfo = new translator_info[physCnt]; 706 *outNumInfo = 0; 707 708 translator_node *pTranNode = fpTranslators; 709 for (; pTranNode; pTranNode = pTranNode->next) { 710 711 const translation_format *format = NULL; 712 translator_info tmpInfo; 713 bool addmatch = false; 714 // avoid the need for a goto 715 716 result = inSource->Seek(0, SEEK_SET); 717 if (result < B_OK) { 718 // break out of the loop if error reading from source 719 delete *outInfo; 720 *outInfo = NULL; 721 break; 722 } else { 723 int32 inputFormatsCount = 0; 724 const translation_format *inputFormats = 725 pTranNode->translator->InputFormats(&inputFormatsCount); 726 727 if (CheckFormats(inputFormats, inputFormatsCount, inHintType, 728 inHintMIME, &format)) { 729 if (format && !pTranNode->translator->Identify(inSource, 730 format, ioExtension, &tmpInfo, inWantType)) 731 addmatch = true; 732 733 } else if (!pTranNode->translator->Identify(inSource, NULL, 734 ioExtension, &tmpInfo, inWantType)) 735 addmatch = true; 736 737 if (addmatch) { 738 // dynamically resize output list 739 // 740 if (physCnt <= *outNumInfo) { 741 physCnt += 10; 742 translator_info *nOut = new translator_info[physCnt]; 743 for (int ix = 0; ix < *outNumInfo; ix++) 744 nOut[ix] = (*outInfo)[ix]; 745 746 delete[] *outInfo; 747 *outInfo = nOut; 748 } 749 750 // XOR to discourage taking advantage of undocumented 751 // features 752 tmpInfo.translator = pTranNode->id; 753 (*outInfo)[(*outNumInfo)++] = tmpInfo; 754 } 755 } 756 } // for (; pTranNode; pTranNode = pTranNode->next) 757 758 // if exited loop WITHOUT errors 759 if (!pTranNode) { 760 761 if (*outNumInfo > 1) 762 qsort(*outInfo, *outNumInfo, sizeof(**outInfo), compare_data); 763 764 if (*outNumInfo > 0) 765 result = B_NO_ERROR; 766 else 767 result = B_NO_TRANSLATOR; 768 } 769 770 release_sem(fSem); 771 772 } // if (acquire_sem(fSem) == B_OK) 773 774 return result; 775 } 776 777 // --------------------------------------------------------------- 778 // GetAllTranslators 779 // 780 // Returns a list of all of the translators stored by this object. 781 // You must delete the list, outList, yourself when you are done 782 // with it. 783 // 784 // Preconditions: 785 // 786 // Parameters: outList, where the list is stored, 787 // (you must delete the list yourself) 788 // outCount, where the count of the items in 789 // the list is stored 790 // 791 // Postconditions: 792 // 793 // Returns: B_BAD_VALUE, if outList or outCount is NULL 794 // B_NOT_INITIALIZED, if the constructor couldn't 795 // create a semaphore 796 // B_NO_ERROR, if successful 797 // --------------------------------------------------------------- 798 status_t 799 BTranslatorRoster::GetAllTranslators( 800 translator_id **outList, int32 *outCount) 801 { 802 if (!outList || !outCount) 803 return B_BAD_VALUE; 804 805 status_t result = B_NOT_INITIALIZED; 806 807 *outList = NULL; 808 *outCount = 0; 809 810 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 811 // count translators 812 translator_node *pTranNode = NULL; 813 for (pTranNode = fpTranslators; pTranNode; pTranNode = pTranNode->next) 814 (*outCount)++; 815 // populate the outList 816 *outList = new translator_id[*outCount]; 817 int32 i = 0; 818 for (pTranNode = fpTranslators; pTranNode; pTranNode = pTranNode->next) 819 (*outList)[i++] = pTranNode->id; 820 821 result = B_NO_ERROR; 822 release_sem(fSem); 823 } 824 825 return result; 826 } 827 828 // --------------------------------------------------------------- 829 // GetTranslatorInfo 830 // 831 // Returns information about the translator with translator_id 832 // forTranslator. outName is the short name of the translator, 833 // outInfo is the verbose name / description of the translator, 834 // and outVersion is the integer representation of the translator 835 // version. 836 // 837 // Preconditions: 838 // 839 // Parameters: forTranslator, identifies which translator 840 // you want info for 841 // outName, the translator name is put here 842 // outInfo, the translator info is put here 843 // outVersion, the translation version is put here 844 // 845 // Postconditions: 846 // 847 // Returns: B_NO_ERROR, if successful, 848 // B_BAD_VALUE, if any parameter is NULL 849 // B_NOT_INITIALIZED, if the constructor couldn't 850 // create a semaphore 851 // B_NO_TRANSLATOR, if forTranslator is not a valid 852 // translator id 853 // --------------------------------------------------------------- 854 status_t 855 BTranslatorRoster::GetTranslatorInfo( 856 translator_id forTranslator, const char **outName, 857 const char **outInfo, int32 *outVersion) 858 { 859 if (!outName || !outInfo || !outVersion) 860 return B_BAD_VALUE; 861 862 status_t result = B_NOT_INITIALIZED; 863 864 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 865 // find the translator we've requested 866 translator_node *pTranNode = FindTranslatorNode(forTranslator); 867 if (!pTranNode) 868 result = B_NO_TRANSLATOR; 869 else { 870 *outName = pTranNode->translator->TranslatorName(); 871 *outInfo = pTranNode->translator->TranslatorInfo(); 872 *outVersion = pTranNode->translator->TranslatorVersion(); 873 874 result = B_NO_ERROR; 875 } 876 release_sem(fSem); 877 } 878 879 return result; 880 } 881 882 // --------------------------------------------------------------- 883 // GetInputFormats 884 // 885 // Returns all of the input formats for the translator 886 // forTranslator. Not all translators publish the input formats 887 // that they accept. 888 // 889 // Preconditions: 890 // 891 // Parameters: forTranslator, identifies which translator 892 // you want info for 893 // outFormats, array of input formats 894 // outNumFormats, number of items in outFormats 895 // 896 // Postconditions: 897 // 898 // Returns: B_NO_ERROR, if successful 899 // B_BAD_VALUE, if either pointer is NULL 900 // B_NOT_INITIALIZED, if the constructor couldn't 901 // create a semaphore 902 // B_NO_TRANSLATOR, if forTranslator is a bad id 903 // --------------------------------------------------------------- 904 status_t 905 BTranslatorRoster::GetInputFormats(translator_id forTranslator, 906 const translation_format **outFormats, int32 *outNumFormats) 907 { 908 if (!outFormats || !outNumFormats) 909 return B_BAD_VALUE; 910 911 status_t result = B_NOT_INITIALIZED; 912 913 *outFormats = NULL; 914 *outNumFormats = 0; 915 916 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 917 // find the translator we've requested 918 translator_node *pTranNode = FindTranslatorNode(forTranslator); 919 if (!pTranNode) 920 result = B_NO_TRANSLATOR; 921 else { 922 *outFormats = pTranNode->translator->InputFormats(outNumFormats); 923 result = B_NO_ERROR; 924 } 925 release_sem(fSem); 926 } 927 928 return result; 929 } 930 931 // --------------------------------------------------------------- 932 // GetOutputFormats 933 // 934 // Returns all of the output formats for the translator 935 // forTranslator. Not all translators publish the output formats 936 // that they accept. 937 // 938 // Preconditions: 939 // 940 // Parameters: forTranslator, identifies which translator 941 // you want info for 942 // outFormats, array of output formats 943 // outNumFormats, number of items in outFormats 944 // 945 // Postconditions: 946 // 947 // Returns: B_NO_ERROR, if successful 948 // B_BAD_VALUE, if either pointer is NULL 949 // B_NOT_INITIALIZED, if the constructor couldn't 950 // create a semaphore 951 // B_NO_TRANSLATOR, if forTranslator is a bad id 952 // --------------------------------------------------------------- 953 status_t 954 BTranslatorRoster::GetOutputFormats(translator_id forTranslator, 955 const translation_format **outFormats, int32 *outNumFormats) 956 { 957 if (!outFormats || !outNumFormats) 958 return B_BAD_VALUE; 959 960 status_t result = B_NOT_INITIALIZED; 961 962 *outFormats = NULL; 963 *outNumFormats = 0; 964 965 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 966 // find the translator we've requested 967 translator_node *pTranNode = FindTranslatorNode(forTranslator); 968 if (!pTranNode) 969 result = B_NO_TRANSLATOR; 970 else { 971 *outFormats = pTranNode->translator->OutputFormats(outNumFormats); 972 result = B_NO_ERROR; 973 } 974 release_sem(fSem); 975 } 976 977 return result; 978 } 979 980 // --------------------------------------------------------------- 981 // Translate 982 // 983 // This function is the whole point of the Translation Kit. 984 // This is for translating the data in inSource to outDestination 985 // using the format inWantOutType. 986 // 987 // Preconditions: 988 // 989 // Parameters: inSource, the data that wants to be translated 990 // ioExtension, configuration data for the translator 991 // inInfo, identifies the translator to use, can be 992 // NULL, calls Identify() if NULL 993 // inHintType, hint for the type of data in 994 // inSource, can be zero if the 995 // type is not known 996 // inHintMIME, hint MIME type of the data 997 // in inSource, can be NULL if 998 // the MIME type is not known 999 // inWantOutType, the desired output type for 1000 // the data in inSource. 1001 // outDestination, where inSource is translated to 1002 // 1003 // Postconditions: 1004 // 1005 // Returns: B_OK, translation successful, 1006 // B_NO_TRANSLATOR, no appropriate translator found 1007 // B_NOT_INITIALIZED, the constructor failed to 1008 // create a semaphore 1009 // B_BAD_VALUE, inSource or outDestination is NULL 1010 // other values, error using inSource 1011 // --------------------------------------------------------------- 1012 status_t 1013 BTranslatorRoster::Translate(BPositionIO *inSource, 1014 const translator_info *inInfo, BMessage *ioExtension, 1015 BPositionIO *outDestination, uint32 inWantOutType, 1016 uint32 inHintType, const char *inHintMIME) 1017 { 1018 if (!inSource || !outDestination) 1019 return B_BAD_VALUE; 1020 1021 if (fSem <= 0) 1022 return B_NOT_INITIALIZED; 1023 1024 status_t result = B_OK; 1025 translator_info stat_info; 1026 1027 if (!inInfo) { 1028 // go look for a suitable translator 1029 inInfo = &stat_info; 1030 1031 result = Identify(inSource, ioExtension, &stat_info, 1032 inHintType, inHintMIME, inWantOutType); 1033 // Identify is a locked function, so it cannot be 1034 // called from code that is already locked 1035 } 1036 1037 if (result >= B_OK && acquire_sem(fSem) == B_OK) { 1038 translator_node *pTranNode = FindTranslatorNode(inInfo->translator); 1039 if (!pTranNode) { 1040 result = B_NO_TRANSLATOR; 1041 } 1042 else { 1043 result = inSource->Seek(0, SEEK_SET); 1044 if (result == B_OK) 1045 result = pTranNode->translator->Translate(inSource, inInfo, 1046 ioExtension, inWantOutType, outDestination); 1047 } 1048 release_sem(fSem); 1049 } 1050 1051 return result; 1052 } 1053 1054 // --------------------------------------------------------------- 1055 // Translate 1056 // 1057 // This function is the whole point of the Translation Kit. 1058 // This is for translating the data in inSource to outDestination 1059 // using the format inWantOutType. 1060 // 1061 // Preconditions: 1062 // 1063 // Parameters: inSource, the data that wants to be translated 1064 // ioExtension, configuration data for the translator 1065 // inTranslator, the translator to use for the 1066 // translation 1067 // inWantOutType, the desired output type for 1068 // the data in inSource. 1069 // outDestination, where inSource is translated to 1070 // 1071 // Postconditions: 1072 // 1073 // Returns: B_OK, translation successful, 1074 // B_NO_TRANSLATOR, inTranslator is an invalid id 1075 // B_NOT_INITIALIZED, the constructor failed to 1076 // create a semaphore 1077 // B_BAD_VALUE, inSource or outDestination is NULL 1078 // other values, error using inSource 1079 // --------------------------------------------------------------- 1080 status_t 1081 BTranslatorRoster::Translate(translator_id inTranslator, 1082 BPositionIO *inSource, BMessage *ioExtension, 1083 BPositionIO *outDestination, uint32 inWantOutType) 1084 { 1085 if (!inSource || !outDestination) 1086 return B_BAD_VALUE; 1087 1088 status_t result = B_NOT_INITIALIZED; 1089 1090 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1091 translator_node *pTranNode = FindTranslatorNode(inTranslator); 1092 if (!pTranNode) 1093 result = B_NO_TRANSLATOR; 1094 else { 1095 result = inSource->Seek(0, SEEK_SET); 1096 if (result == B_OK) { 1097 translator_info traninfo; 1098 result = pTranNode->translator->Identify(inSource, NULL, 1099 ioExtension, &traninfo, inWantOutType); 1100 if (result == B_OK) { 1101 result = inSource->Seek(0, SEEK_SET); 1102 if (result == B_OK) { 1103 result = pTranNode->translator->Translate(inSource, 1104 &traninfo, ioExtension, inWantOutType, 1105 outDestination); 1106 } 1107 } 1108 } 1109 } 1110 release_sem(fSem); 1111 } 1112 1113 return result; 1114 } 1115 1116 // --------------------------------------------------------------- 1117 // MakeConfigurationView 1118 // 1119 // Returns outView, a BView for configuring the translator 1120 // forTranslator. Not all translators support this. 1121 // 1122 // Preconditions: 1123 // 1124 // Parameters: forTranslator, the translator the view is for 1125 // ioExtension, the configuration data for 1126 // the translator 1127 // outView, the view for configuring the 1128 // translator 1129 // outExtent, the bounds for the view, the view 1130 // can be resized 1131 // 1132 // Postconditions: 1133 // 1134 // Returns: B_OK, success, 1135 // B_NO_TRANSLATOR, inTranslator is an invalid id 1136 // B_NOT_INITIALIZED, the constructor failed to 1137 // create a semaphore 1138 // B_BAD_VALUE, inSource or outDestination is NULL 1139 // other values, error using inSource 1140 // --------------------------------------------------------------- 1141 status_t 1142 BTranslatorRoster::MakeConfigurationView( 1143 translator_id forTranslator, BMessage *ioExtension, 1144 BView **outView, BRect *outExtent) 1145 { 1146 if (!outView || !outExtent) 1147 return B_BAD_VALUE; 1148 1149 status_t result = B_NOT_INITIALIZED; 1150 1151 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1152 translator_node *pTranNode = FindTranslatorNode(forTranslator); 1153 if (!pTranNode) 1154 result = B_NO_TRANSLATOR; 1155 else 1156 result = pTranNode->translator->MakeConfigurationView(ioExtension, 1157 outView, outExtent); 1158 1159 release_sem(fSem); 1160 } 1161 1162 return result; 1163 } 1164 1165 // --------------------------------------------------------------- 1166 // GetConfigurationMessage 1167 // 1168 // Gets the configuration setttings for the translator 1169 // forTranslator and puts the settings into ioExtension. 1170 // 1171 // Preconditions: 1172 // 1173 // Parameters: forTranslator, the translator the info 1174 // is for 1175 // ioExtension, the configuration data for 1176 // the translator is stored here 1177 // 1178 // Postconditions: 1179 // 1180 // Returns: B_OK, success, 1181 // B_NO_TRANSLATOR, inTranslator is an invalid id 1182 // B_NOT_INITIALIZED, the constructor failed to 1183 // create a semaphore 1184 // B_BAD_VALUE, inSource or outDestination is NULL 1185 // other values, error using inSource 1186 // --------------------------------------------------------------- 1187 status_t 1188 BTranslatorRoster::GetConfigurationMessage( 1189 translator_id forTranslator, BMessage *ioExtension) 1190 { 1191 if (!ioExtension) 1192 return B_BAD_VALUE; 1193 1194 status_t result = B_NOT_INITIALIZED; 1195 1196 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1197 translator_node *pTranNode = FindTranslatorNode(forTranslator); 1198 if (!pTranNode) 1199 result = B_NO_TRANSLATOR; 1200 else 1201 result = 1202 pTranNode->translator->GetConfigurationMessage(ioExtension); 1203 1204 release_sem(fSem); 1205 } 1206 1207 return result; 1208 } 1209 1210 // --------------------------------------------------------------- 1211 // GetRefFor 1212 // 1213 // Gets the entry_ref for the given translator. 1214 // 1215 // Preconditions: 1216 // 1217 // Parameters: forTranslator, the translator the info 1218 // is for 1219 // entry_ref, where the entry ref is stored 1220 // 1221 // Postconditions: 1222 // 1223 // Returns: B_OK, success, 1224 // B_NO_TRANSLATOR, translator is an invalid id 1225 // B_NOT_INITIALIZED, the constructor failed to 1226 // create a semaphore 1227 // B_BAD_VALUE, inSource or outDestination is NULL 1228 // other values, error using inSource 1229 // --------------------------------------------------------------- 1230 status_t 1231 BTranslatorRoster::GetRefFor(translator_id translator, 1232 entry_ref *out_ref) 1233 { 1234 if (!out_ref) 1235 return B_BAD_VALUE; 1236 1237 status_t result = B_NOT_INITIALIZED; 1238 1239 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1240 translator_node *pTranNode = FindTranslatorNode(translator); 1241 if (!pTranNode) 1242 result = B_NO_TRANSLATOR; 1243 else { 1244 if (pTranNode->path[0] == '\0') 1245 result = B_ERROR; 1246 else 1247 result = get_ref_for_path(pTranNode->path, out_ref); 1248 } 1249 release_sem(fSem); 1250 } 1251 1252 return result; 1253 } 1254 1255 1256 // --------------------------------------------------------------- 1257 // FindTranslatorNode 1258 // 1259 // Finds the translator_node that holds the translator with 1260 // the translator_id id. 1261 // 1262 // Preconditions: 1263 // 1264 // Parameters: id, the translator you want a translator_node for 1265 // 1266 // Postconditions: 1267 // 1268 // Returns: NULL if id is not a valid translator_id, 1269 // pointer to the translator_node that holds the 1270 // translator id 1271 // --------------------------------------------------------------- 1272 translator_node * 1273 BTranslatorRoster::FindTranslatorNode(translator_id id) 1274 { 1275 translator_node *pTranNode = NULL; 1276 for (pTranNode = fpTranslators; pTranNode; pTranNode = pTranNode->next) 1277 if (pTranNode->id == id) 1278 break; 1279 1280 return pTranNode; 1281 } 1282 1283 const char * 1284 get_file_name(const char *path) 1285 { 1286 const char *file_name = strrchr(path, '/'); 1287 if (file_name) 1288 file_name++; 1289 else 1290 file_name = path; 1291 1292 return file_name; 1293 } 1294 1295 // --------------------------------------------------------------- 1296 // LoadTranslator 1297 // 1298 // Loads the translator from path into memory and adds it to 1299 // the BTranslatorRoster. 1300 // 1301 // Preconditions: This should only be called inside of locked 1302 // code. 1303 // 1304 // Parameters: path, the path for the translator to be loaded 1305 // 1306 // Postconditions: 1307 // 1308 // Returns: B_BAD_VALUE, if path is NULL, 1309 // B_NO_ERROR, if all is well, 1310 // other values if error loading add ons 1311 // --------------------------------------------------------------- 1312 status_t 1313 BTranslatorRoster::LoadTranslator(const char *path) 1314 { 1315 if (!path) 1316 return B_BAD_VALUE; 1317 1318 // check that this ref is not already loaded 1319 const char *file_name = get_file_name(path); 1320 1321 // If a translator with the same filename has already 1322 // been loaded, do not load the current translator and 1323 // return no error. This code is not fool proof, however. 1324 for (translator_node *i = fpTranslators; i; i = i->next) 1325 if (!strcmp(file_name, get_file_name(i->path))) 1326 return B_NO_ERROR; 1327 1328 image_id image = load_add_on(path); 1329 // Load the data and code for the Translator into memory 1330 if (image < 0) 1331 return image; 1332 1333 // Function pointer used to create post R4.5 style translators 1334 BTranslator *(*pMakeNthTranslator)(int32 n, image_id you, uint32 flags, ...); 1335 1336 status_t err = get_image_symbol(image, "make_nth_translator", 1337 B_SYMBOL_TYPE_TEXT, reinterpret_cast<void **> (&pMakeNthTranslator)); 1338 if (!err) { 1339 // If the translator add-on supports the post R4.5 1340 // translator creation mechanism, keep loading translators 1341 // until MakeNthTranslator stops returning them. 1342 BTranslator *ptran = NULL; 1343 for (int32 n = 0; (ptran = pMakeNthTranslator(n, image, 0)); n++) 1344 AddTranslatorToList(ptran, path, image, false); 1345 1346 return B_NO_ERROR; 1347 1348 } else { 1349 // If the translator add-on is in the R4.0 / R4.5 format 1350 translator_data trand; 1351 trand.translatorName = NULL; 1352 trand.translatorInfo = NULL; 1353 trand.translatorVersion = 0; 1354 trand.inputFormats = NULL; 1355 trand.outputFormats = NULL; 1356 trand.Identify = NULL; 1357 trand.Translate = NULL; 1358 trand.MakeConfig = NULL; 1359 trand.GetConfigMessage = NULL; 1360 1361 char *name = NULL, *info = NULL; 1362 translation_format *ins = NULL, *outs = NULL; 1363 1364 // find all the symbols 1365 err = get_image_symbol(image, "translatorName", B_SYMBOL_TYPE_DATA, 1366 reinterpret_cast<void **> (&name)); 1367 if (err) 1368 name = NULL; 1369 else if (!err && get_image_symbol(image, "translatorInfo", 1370 B_SYMBOL_TYPE_DATA, reinterpret_cast<void **> (&info))) 1371 info = NULL; 1372 1373 int32 *pn = NULL; 1374 if (!err) { 1375 err = get_image_symbol(image, "translatorVersion", 1376 B_SYMBOL_TYPE_DATA, reinterpret_cast<void **> (&pn)); 1377 if (!err && (pn != NULL)) 1378 trand.translatorVersion = *pn; 1379 } 1380 1381 if (!err && get_image_symbol(image, "inputFormats", 1382 B_SYMBOL_TYPE_DATA, 1383 reinterpret_cast<void **> (&ins))) 1384 ins = NULL; 1385 1386 if (!err && get_image_symbol(image, "outputFormats", 1387 B_SYMBOL_TYPE_DATA, 1388 reinterpret_cast<void **> (&outs))) 1389 outs = NULL; 1390 1391 if (!err) 1392 err = get_image_symbol(image, "Identify", 1393 B_SYMBOL_TYPE_TEXT, 1394 reinterpret_cast<void **> (&trand.Identify)); 1395 1396 if (!err) 1397 err = get_image_symbol(image, "Translate", 1398 B_SYMBOL_TYPE_TEXT, 1399 reinterpret_cast<void **> (&trand.Translate)); 1400 1401 if (!err && get_image_symbol(image, "MakeConfig", 1402 B_SYMBOL_TYPE_TEXT, 1403 reinterpret_cast<void **> (&trand.MakeConfig))) 1404 trand.MakeConfig = NULL; 1405 1406 if (!err && get_image_symbol(image, "GetConfigMessage", 1407 B_SYMBOL_TYPE_TEXT, 1408 reinterpret_cast<void **> (&trand.GetConfigMessage))) 1409 trand.GetConfigMessage = NULL; 1410 1411 trand.translatorName = name; 1412 trand.translatorInfo = info; 1413 trand.inputFormats = ins; 1414 trand.outputFormats = outs; 1415 1416 // if add-on is not in the correct format, return with error 1417 if (err) 1418 return err; 1419 1420 // add this translator to the list 1421 BFuncTranslator *pFuncTran = new BFuncTranslator(&trand); 1422 AddTranslatorToList(pFuncTran, path, image, false); 1423 // do not call Acquire() on ptran because I want it to be 1424 // deleted the first time Release() is called on it. 1425 1426 return B_NO_ERROR; 1427 } 1428 } 1429 1430 // --------------------------------------------------------------- 1431 // LoadDir 1432 // 1433 // Loads all of the translators in the directory path 1434 // 1435 // Preconditions: should only be called inside locked code 1436 // 1437 // Parameters: path, the directory of translators to load 1438 // loadErr, the return code 1439 // nLoaded, number of translators loaded 1440 // 1441 // Postconditions: 1442 // 1443 // Returns: B_FILE_NOT_FOUND, if the path is NULL or invalid 1444 // other errors if LoadTranslator failed 1445 // --------------------------------------------------------------- 1446 void 1447 BTranslatorRoster::LoadDir(const char *path, int32 &loadErr, int32 &nLoaded) 1448 { 1449 if (!path) { 1450 loadErr = B_FILE_NOT_FOUND; 1451 return; 1452 } 1453 1454 loadErr = B_OK; 1455 DIR *dir = opendir(path); 1456 if (!dir) { 1457 loadErr = B_FILE_NOT_FOUND; 1458 return; 1459 } 1460 struct dirent *dent; 1461 struct stat stbuf; 1462 char cwd[PATH_MAX] = ""; 1463 while (NULL != (dent = readdir(dir))) { 1464 strcpy(cwd, path); 1465 strcat(cwd, "/"); 1466 strcat(cwd, dent->d_name); 1467 status_t err = stat(cwd, &stbuf); 1468 1469 if (!err && S_ISREG(stbuf.st_mode) && 1470 strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { 1471 1472 err = LoadTranslator(cwd); 1473 if (err == B_OK) 1474 nLoaded++; 1475 else 1476 loadErr = err; 1477 } 1478 } 1479 closedir(dir); 1480 } 1481 1482 // --------------------------------------------------------------- 1483 // CheckFormats 1484 // 1485 // Function used to determine if hintType and hintMIME can be 1486 // used to find the desired translation_format. 1487 // 1488 // Preconditions: Should only be called from inside locked code 1489 // 1490 // Parameters: inputFormats, the formats check against the hints 1491 // inputFormatsCount, number of items in inputFormats 1492 // hintType, the type this function is looking for 1493 // hintMIME, the MIME type this function is looking 1494 // for 1495 // outFormat, NULL if no suitable translation_format 1496 // from inputFormats was found, not NULL 1497 // if a translation_format matching the 1498 // hints was found 1499 // 1500 // 1501 // Postconditions: 1502 // 1503 // Returns: true, if a determination could be made 1504 // false, if indentification must be done 1505 // --------------------------------------------------------------- 1506 bool 1507 BTranslatorRoster::CheckFormats(const translation_format *inputFormats, 1508 int32 inputFormatsCount, uint32 hintType, const char *hintMIME, 1509 const translation_format **outFormat) 1510 { 1511 if (!inputFormats || inputFormatsCount <= 0 || !outFormat) 1512 return false; 1513 1514 *outFormat = NULL; 1515 1516 // return false if we can't use hints for this module 1517 if (!hintType && !hintMIME) 1518 return false; 1519 1520 // check for the length of the MIME string, since it may be just a prefix 1521 // so we use strncmp(). 1522 int mlen = 0; 1523 if (hintMIME) 1524 mlen = strlen(hintMIME); 1525 1526 // scan for suitable format 1527 const translation_format *fmt = inputFormats; 1528 for (int32 i = 0; i < inputFormatsCount && fmt->type; i++, fmt++) { 1529 if ((fmt->type == hintType) || 1530 (hintMIME && mlen && !strncmp(fmt->MIME, hintMIME, mlen))) { 1531 *outFormat = fmt; 1532 return true; 1533 } 1534 } 1535 // the module did export formats, but none matched. 1536 // we return true (uses formats) but set outFormat to NULL 1537 return true; 1538 } 1539 1540 // --------------------------------------------------------------- 1541 // AddTranslatorToList 1542 // 1543 // Adds a BTranslator based object to the list of translators 1544 // stored by the BTranslatorRoster. 1545 // 1546 // Preconditions: Should only be called inside locked code 1547 // 1548 // Parameters: translator, the translator to add to this object 1549 // 1550 // Postconditions: 1551 // 1552 // Returns: B_BAD_VALUE, if translator is NULL 1553 // B_OK, if not 1554 // --------------------------------------------------------------- 1555 status_t 1556 BTranslatorRoster::AddTranslatorToList(BTranslator *translator) 1557 { 1558 return AddTranslatorToList(translator, "", -1, true); 1559 // add translator to list with no add-on image to unload, 1560 // and call Acquire() on it 1561 } 1562 1563 // --------------------------------------------------------------- 1564 // AddTranslatorToList 1565 // 1566 // Adds a BTranslator based object to the list of translators 1567 // stored by the BTranslatorRoster. 1568 // 1569 // Preconditions: Should only be called inside locked code 1570 // 1571 // Parameters: translator, the translator to add to this object 1572 // path, the path the translator was loaded from 1573 // image, the image the translator was loaded from 1574 // acquire, if true Acquire() is called on the 1575 // translator 1576 // 1577 // Postconditions: 1578 // 1579 // Returns: B_BAD_VALUE, if translator is NULL 1580 // B_OK, if not 1581 // --------------------------------------------------------------- 1582 status_t 1583 BTranslatorRoster::AddTranslatorToList(BTranslator *translator, 1584 const char *path, image_id image, bool acquire) 1585 { 1586 if (!translator || !path) 1587 return B_BAD_VALUE; 1588 1589 translator_node *pTranNode = new translator_node; 1590 1591 if (acquire) 1592 pTranNode->translator = translator->Acquire(); 1593 else 1594 pTranNode->translator = translator; 1595 1596 if (fpTranslators) 1597 pTranNode->id = fpLastTranslator->id + 1; 1598 else 1599 pTranNode->id = 1; 1600 1601 pTranNode->path = new char[strlen(path) + 1]; 1602 strcpy(pTranNode->path, path); 1603 pTranNode->image = image; 1604 pTranNode->next = NULL; 1605 if (!fpTranslators) 1606 fpTranslators = fpLastTranslator = pTranNode; 1607 else { 1608 fpLastTranslator->next = pTranNode; 1609 fpLastTranslator = pTranNode; 1610 } 1611 1612 return B_OK; 1613 } 1614 1615 // --------------------------------------------------------------- 1616 // ReservedTranslatorRoster1 1617 // 1618 // It does nothing! :) Its here only for past/future binary 1619 // compatibility. 1620 // 1621 // Preconditions: 1622 // 1623 // Parameters: 1624 // 1625 // Postconditions: 1626 // 1627 // Returns: 1628 // --------------------------------------------------------------- 1629 void 1630 BTranslatorRoster::ReservedTranslatorRoster1() 1631 { 1632 } 1633 1634 // --------------------------------------------------------------- 1635 // ReservedTranslatorRoster2 1636 // 1637 // It does nothing! :) Its here only for past/future binary 1638 // compatibility. 1639 // 1640 // Preconditions: 1641 // 1642 // Parameters: 1643 // 1644 // Postconditions: 1645 // 1646 // Returns: 1647 // --------------------------------------------------------------- 1648 void 1649 BTranslatorRoster::ReservedTranslatorRoster2() 1650 { 1651 } 1652 1653 // --------------------------------------------------------------- 1654 // ReservedTranslatorRoster3 1655 // 1656 // It does nothing! :) Its here only for past/future binary 1657 // compatibility. 1658 // 1659 // Preconditions: 1660 // 1661 // Parameters: 1662 // 1663 // Postconditions: 1664 // 1665 // Returns: 1666 // --------------------------------------------------------------- 1667 void 1668 BTranslatorRoster::ReservedTranslatorRoster3() 1669 { 1670 } 1671 1672 // --------------------------------------------------------------- 1673 // ReservedTranslatorRoster4 1674 // 1675 // It does nothing! :) Its here only for past/future binary 1676 // compatibility. 1677 // 1678 // Preconditions: 1679 // 1680 // Parameters: 1681 // 1682 // Postconditions: 1683 // 1684 // Returns: 1685 // --------------------------------------------------------------- 1686 void 1687 BTranslatorRoster::ReservedTranslatorRoster4() 1688 { 1689 } 1690 1691 // --------------------------------------------------------------- 1692 // ReservedTranslatorRoster5 1693 // 1694 // It does nothing! :) Its here only for past/future binary 1695 // compatibility. 1696 // 1697 // Preconditions: 1698 // 1699 // Parameters: 1700 // 1701 // Postconditions: 1702 // 1703 // Returns: 1704 // --------------------------------------------------------------- 1705 void 1706 BTranslatorRoster::ReservedTranslatorRoster5() 1707 { 1708 } 1709 1710 // --------------------------------------------------------------- 1711 // ReservedTranslatorRoster6 1712 // 1713 // It does nothing! :) Its here only for past/future binary 1714 // compatibility. 1715 // 1716 // Preconditions: 1717 // 1718 // Parameters: 1719 // 1720 // Postconditions: 1721 // 1722 // Returns: 1723 // --------------------------------------------------------------- 1724 void 1725 BTranslatorRoster::ReservedTranslatorRoster6() 1726 { 1727 } 1728 1729