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 = 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 = 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 B_TRANSLATION_CURRENT_VERSION/100, 333 (B_TRANSLATION_CURRENT_VERSION/10)%10, 334 B_TRANSLATION_CURRENT_VERSION%10, 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 // Determine if translator is already in the list 493 translator_node *pNode = fpTranslators; 494 while (pNode) { 495 // If translator is in the list, don't add it 496 if (!strcmp(pNode->translator->TranslatorName(), 497 translator->TranslatorName())) { 498 result = B_OK; 499 break; 500 } 501 pNode = pNode->next; 502 } 503 504 // if translator is NOT in the list, add it 505 if (!pNode) 506 result = AddTranslatorToList(translator); 507 508 release_sem(fSem); 509 } 510 511 return result; 512 } 513 514 // --------------------------------------------------------------- 515 // Identify 516 // 517 // This function determines which translator is best suited 518 // to convert the data from inSource. 519 // 520 // Preconditions: 521 // 522 // Parameters: inSource, the data to be translated, 523 // ioExtension, the configuration data for the 524 // translator 525 // outInfo, the information about the chosen 526 // translator is put here 527 // inHintType, a hint about the type of data 528 // that is in inSource, can be 529 // zero if type is not known 530 // inHintMIME, a hint about the MIME type of 531 // data that is in inSource, 532 // can be NULL 533 // inWantType, the desired output type for 534 // inSource, if zero, any type 535 // is ok. 536 // 537 // Postconditions: 538 // 539 // Returns: B_OK, identification of inSource was successful, 540 // B_NO_TRANSLATOR, no appropriate translator found 541 // B_NOT_INITIALIZED, the constructor failed to 542 // create a semaphore 543 // B_BAD_VALUE, inSource or outInfo is NULL 544 // other values, error using inSource 545 // --------------------------------------------------------------- 546 status_t 547 BTranslatorRoster::Identify(BPositionIO *inSource, 548 BMessage *ioExtension, translator_info *outInfo, 549 uint32 inHintType, const char *inHintMIME, 550 uint32 inWantType) 551 { 552 if (!inSource || !outInfo) 553 return B_BAD_VALUE; 554 555 status_t result = B_NOT_INITIALIZED; 556 bool bFoundMatch = false; 557 558 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 559 560 translator_node *pTranNode = fpTranslators; 561 float bestWeight = 0.0; 562 for (; pTranNode; pTranNode = pTranNode->next) { 563 564 const translation_format *format = NULL; 565 translator_info tmpInfo; 566 float weight = 0.0; 567 bool addmatch = false; 568 // eliminates need for a goto 569 570 result = inSource->Seek(0, SEEK_SET); 571 if (result == B_OK) { 572 573 int32 inputFormatsCount = 0; 574 const translation_format *inputFormats = 575 pTranNode->translator->InputFormats(&inputFormatsCount); 576 577 if (CheckFormats(inputFormats, inputFormatsCount, inHintType, 578 inHintMIME, &format)) { 579 580 // after checking the formats for hints, we still need to make 581 // sure the translator recognizes the data and can output the 582 // desired format, so we call its' Identify() function. 583 if (format && !pTranNode->translator->Identify(inSource, 584 format, ioExtension, &tmpInfo, inWantType)) 585 addmatch = true; 586 587 } else if (!pTranNode->translator->Identify(inSource, NULL, 588 ioExtension, &tmpInfo, inWantType)) 589 addmatch = true; 590 591 if (addmatch) { 592 weight = tmpInfo.quality * tmpInfo.capability; 593 594 // Since many kinds of data can look like text, 595 // don't choose the text format if it has been identified 596 // as belonging to a different group. 597 if (bFoundMatch && outInfo->group == B_TRANSLATOR_TEXT && 598 tmpInfo.group != B_TRANSLATOR_TEXT) 599 bestWeight = 0.0; 600 else if (bFoundMatch && tmpInfo.group == B_TRANSLATOR_TEXT && 601 outInfo->group != B_TRANSLATOR_TEXT) 602 weight = 0.0; 603 604 if (weight > bestWeight) { 605 bFoundMatch = true; 606 bestWeight = weight; 607 608 tmpInfo.translator = pTranNode->id; 609 outInfo->type = tmpInfo.type; 610 outInfo->translator = tmpInfo.translator; 611 outInfo->group = tmpInfo.group; 612 outInfo->quality = tmpInfo.quality; 613 outInfo->capability = tmpInfo.capability; 614 strcpy(outInfo->name, tmpInfo.name); 615 strcpy(outInfo->MIME, tmpInfo.MIME); 616 } 617 } 618 } // if (result == B_OK) 619 } // for (; pTranNode; pTranNode = pTranNode->next) 620 621 if (bFoundMatch) 622 result = B_NO_ERROR; 623 else if (result == B_OK) 624 result = B_NO_TRANSLATOR; 625 626 release_sem(fSem); 627 } // if (acquire_sem(fSem) == B_OK) 628 629 return result; 630 } 631 632 // --------------------------------------------------------------- 633 // compare_data 634 // 635 // This function is not a member of BTranslatorRoster, but it is 636 // used by the GetTranslators() member function as the function 637 // passed to qsort to sort the translators from best to worst. 638 // 639 // Preconditions: 640 // 641 // Parameters: a, pointer to translator_info structure to be 642 // compared to b 643 // b, pointer to translator_info structure to be 644 // compared to a 645 // 646 // Postconditions: 647 // 648 // Returns: < 0 if a is less desirable than b, 649 // 0 if a as good as b, 650 // > 0 if a is more desirable than b 651 // --------------------------------------------------------------- 652 static int 653 compare_data(const void *a, const void *b) 654 { 655 register const translator_info *ai = 656 reinterpret_cast<const translator_info *> (a); 657 658 register const translator_info *bi = 659 reinterpret_cast<const translator_info *> (b); 660 661 return static_cast<int> (- ai->quality * ai->capability + 662 bi->quality * bi->capability); 663 } 664 665 // --------------------------------------------------------------- 666 // GetTranslators 667 // 668 // Finds all translators capable of handling the data in inSource 669 // and puts them into the outInfo array (which you must delete 670 // yourself when you are done with it). Specifying a value for 671 // inHintType, inHintMIME and/or inWantType causes only the 672 // translators that satisfy them to be included in the outInfo. 673 // 674 // Preconditions: 675 // 676 // Parameters: inSource, the data that wants to be translated 677 // ioExtension, configuration data for the translator 678 // outInfo, the array of acceptable translators is 679 // stored here if the function succeeds 680 // outNumInfo, number of entries in outInfo 681 // inHintType, hint for the type of data in 682 // inSource, can be zero if the 683 // type is not known 684 // inHintMIME, hint MIME type of the data 685 // in inSource, can be NULL if 686 // the MIME type is not known 687 // inWantType, the desired output type for 688 // the data in inSource, can be zero 689 // for any type. 690 // 691 // Postconditions: 692 // 693 // Returns: B_OK, successfully indentified the data in inSource 694 // B_NO_TRANSLATOR, no translator could handle inSource 695 // B_NOT_INITIALIZED, the constructore failed to create 696 // a semaphore 697 // B_BAD_VALUE, inSource, outInfo, or outNumInfo is NULL 698 // other errors, problems using inSource 699 // --------------------------------------------------------------- 700 status_t 701 BTranslatorRoster::GetTranslators(BPositionIO *inSource, 702 BMessage *ioExtension, translator_info **outInfo, 703 int32 *outNumInfo, uint32 inHintType, 704 const char *inHintMIME, uint32 inWantType) 705 { 706 if (!inSource || !outInfo || !outNumInfo) 707 return B_BAD_VALUE; 708 709 status_t result = B_NOT_INITIALIZED; 710 711 *outInfo = NULL; 712 *outNumInfo = 0; 713 714 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 715 716 int32 physCnt = 10; 717 *outInfo = new translator_info[physCnt]; 718 *outNumInfo = 0; 719 720 translator_node *pTranNode = fpTranslators; 721 for (; pTranNode; pTranNode = pTranNode->next) { 722 723 const translation_format *format = NULL; 724 translator_info tmpInfo; 725 bool addmatch = false; 726 // avoid the need for a goto 727 728 result = inSource->Seek(0, SEEK_SET); 729 if (result < B_OK) { 730 // break out of the loop if error reading from source 731 delete *outInfo; 732 *outInfo = NULL; 733 break; 734 } else { 735 int32 inputFormatsCount = 0; 736 const translation_format *inputFormats = 737 pTranNode->translator->InputFormats(&inputFormatsCount); 738 739 if (CheckFormats(inputFormats, inputFormatsCount, inHintType, 740 inHintMIME, &format)) { 741 if (format && !pTranNode->translator->Identify(inSource, 742 format, ioExtension, &tmpInfo, inWantType)) 743 addmatch = true; 744 745 } else if (!pTranNode->translator->Identify(inSource, NULL, 746 ioExtension, &tmpInfo, inWantType)) 747 addmatch = true; 748 749 if (addmatch) { 750 // dynamically resize output list 751 // 752 if (physCnt <= *outNumInfo) { 753 physCnt += 10; 754 translator_info *nOut = new translator_info[physCnt]; 755 for (int ix = 0; ix < *outNumInfo; ix++) 756 nOut[ix] = (*outInfo)[ix]; 757 758 delete[] *outInfo; 759 *outInfo = nOut; 760 } 761 762 // XOR to discourage taking advantage of undocumented 763 // features 764 tmpInfo.translator = pTranNode->id; 765 (*outInfo)[(*outNumInfo)++] = tmpInfo; 766 } 767 } 768 } // for (; pTranNode; pTranNode = pTranNode->next) 769 770 // if exited loop WITHOUT errors 771 if (!pTranNode) { 772 773 if (*outNumInfo > 1) 774 qsort(*outInfo, *outNumInfo, sizeof(**outInfo), compare_data); 775 776 if (*outNumInfo > 0) 777 result = B_NO_ERROR; 778 else 779 result = B_NO_TRANSLATOR; 780 } 781 782 release_sem(fSem); 783 784 } // if (acquire_sem(fSem) == B_OK) 785 786 return result; 787 } 788 789 // --------------------------------------------------------------- 790 // GetAllTranslators 791 // 792 // Returns a list of all of the translators stored by this object. 793 // You must delete the list, outList, yourself when you are done 794 // with it. 795 // 796 // Preconditions: 797 // 798 // Parameters: outList, where the list is stored, 799 // (you must delete the list yourself) 800 // outCount, where the count of the items in 801 // the list is stored 802 // 803 // Postconditions: 804 // 805 // Returns: B_BAD_VALUE, if outList or outCount is NULL 806 // B_NOT_INITIALIZED, if the constructor couldn't 807 // create a semaphore 808 // B_NO_ERROR, if successful 809 // --------------------------------------------------------------- 810 status_t 811 BTranslatorRoster::GetAllTranslators( 812 translator_id **outList, int32 *outCount) 813 { 814 if (!outList || !outCount) 815 return B_BAD_VALUE; 816 817 status_t result = B_NOT_INITIALIZED; 818 819 *outList = NULL; 820 *outCount = 0; 821 822 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 823 // count handlers 824 translator_node *pTranNode = NULL; 825 for (pTranNode = fpTranslators; pTranNode; pTranNode = pTranNode->next) 826 (*outCount)++; 827 *outList = new translator_id[*outCount]; 828 *outCount = 0; 829 for (pTranNode = fpTranslators; pTranNode; pTranNode = pTranNode->next) 830 (*outList)[(*outCount)++] = pTranNode->id; 831 832 result = B_NO_ERROR; 833 release_sem(fSem); 834 } 835 836 return result; 837 } 838 839 // --------------------------------------------------------------- 840 // GetTranslatorInfo 841 // 842 // Returns information about the translator with translator_id 843 // forTranslator. outName is the short name of the translator, 844 // outInfo is the verbose name / description of the translator, 845 // and outVersion is the integer representation of the translator 846 // version. 847 // 848 // Preconditions: 849 // 850 // Parameters: forTranslator, identifies which translator 851 // you want info for 852 // outName, the translator name is put here 853 // outInfo, the translator info is put here 854 // outVersion, the translation version is put here 855 // 856 // Postconditions: 857 // 858 // Returns: B_NO_ERROR, if successful, 859 // B_BAD_VALUE, if any parameter is NULL 860 // B_NOT_INITIALIZED, if the constructor couldn't 861 // create a semaphore 862 // B_NO_TRANSLATOR, if forTranslator is not a valid 863 // translator id 864 // --------------------------------------------------------------- 865 status_t 866 BTranslatorRoster::GetTranslatorInfo( 867 translator_id forTranslator, const char **outName, 868 const char **outInfo, int32 *outVersion) 869 { 870 if (!outName || !outInfo || !outVersion) 871 return B_BAD_VALUE; 872 873 status_t result = B_NOT_INITIALIZED; 874 875 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 876 // find the translator we've requested 877 translator_node *pTranNode = FindTranslatorNode(forTranslator); 878 if (!pTranNode) 879 result = B_NO_TRANSLATOR; 880 else { 881 *outName = pTranNode->translator->TranslatorName(); 882 *outInfo = pTranNode->translator->TranslatorInfo(); 883 *outVersion = pTranNode->translator->TranslatorVersion(); 884 885 result = B_NO_ERROR; 886 } 887 release_sem(fSem); 888 } 889 890 return result; 891 } 892 893 // --------------------------------------------------------------- 894 // GetInputFormats 895 // 896 // Returns all of the input formats for the translator 897 // forTranslator. Not all translators publish the input formats 898 // that they accept. 899 // 900 // Preconditions: 901 // 902 // Parameters: forTranslator, identifies which translator 903 // you want info for 904 // outFormats, array of input formats 905 // outNumFormats, number of items in outFormats 906 // 907 // Postconditions: 908 // 909 // Returns: B_NO_ERROR, if successful 910 // B_BAD_VALUE, if either pointer is NULL 911 // B_NOT_INITIALIZED, if the constructor couldn't 912 // create a semaphore 913 // B_NO_TRANSLATOR, if forTranslator is a bad id 914 // --------------------------------------------------------------- 915 status_t 916 BTranslatorRoster::GetInputFormats(translator_id forTranslator, 917 const translation_format **outFormats, int32 *outNumFormats) 918 { 919 if (!outFormats || !outNumFormats) 920 return B_BAD_VALUE; 921 922 status_t result = B_NOT_INITIALIZED; 923 924 *outFormats = NULL; 925 *outNumFormats = 0; 926 927 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 928 // find the translator we've requested 929 translator_node *pTranNode = FindTranslatorNode(forTranslator); 930 if (!pTranNode) 931 result = B_NO_TRANSLATOR; 932 else { 933 *outFormats = pTranNode->translator->InputFormats(outNumFormats); 934 result = B_NO_ERROR; 935 } 936 release_sem(fSem); 937 } 938 939 return result; 940 } 941 942 // --------------------------------------------------------------- 943 // GetOutputFormats 944 // 945 // Returns all of the output formats for the translator 946 // forTranslator. Not all translators publish the output formats 947 // that they accept. 948 // 949 // Preconditions: 950 // 951 // Parameters: forTranslator, identifies which translator 952 // you want info for 953 // outFormats, array of output formats 954 // outNumFormats, number of items in outFormats 955 // 956 // Postconditions: 957 // 958 // Returns: B_NO_ERROR, if successful 959 // B_BAD_VALUE, if either pointer is NULL 960 // B_NOT_INITIALIZED, if the constructor couldn't 961 // create a semaphore 962 // B_NO_TRANSLATOR, if forTranslator is a bad id 963 // --------------------------------------------------------------- 964 status_t 965 BTranslatorRoster::GetOutputFormats(translator_id forTranslator, 966 const translation_format **outFormats, int32 *outNumFormats) 967 { 968 if (!outFormats || !outNumFormats) 969 return B_BAD_VALUE; 970 971 status_t result = B_NOT_INITIALIZED; 972 973 *outFormats = NULL; 974 *outNumFormats = 0; 975 976 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 977 // find the translator we've requested 978 translator_node *pTranNode = FindTranslatorNode(forTranslator); 979 if (!pTranNode) 980 result = B_NO_TRANSLATOR; 981 else { 982 *outFormats = pTranNode->translator->OutputFormats(outNumFormats); 983 result = B_NO_ERROR; 984 } 985 release_sem(fSem); 986 } 987 988 return result; 989 } 990 991 // --------------------------------------------------------------- 992 // Translate 993 // 994 // This function is the whole point of the Translation Kit. 995 // This is for translating the data in inSource to outDestination 996 // using the format inWantOutType. 997 // 998 // Preconditions: 999 // 1000 // Parameters: inSource, the data that wants to be translated 1001 // ioExtension, configuration data for the translator 1002 // inInfo, identifies the translator to use, can be 1003 // NULL, calls Identify() if NULL 1004 // inHintType, hint for the type of data in 1005 // inSource, can be zero if the 1006 // type is not known 1007 // inHintMIME, hint MIME type of the data 1008 // in inSource, can be NULL if 1009 // the MIME type is not known 1010 // inWantOutType, the desired output type for 1011 // the data in inSource. 1012 // outDestination, where inSource is translated to 1013 // 1014 // Postconditions: 1015 // 1016 // Returns: B_OK, translation successful, 1017 // B_NO_TRANSLATOR, no appropriate translator found 1018 // B_NOT_INITIALIZED, the constructor failed to 1019 // create a semaphore 1020 // B_BAD_VALUE, inSource or outDestination is NULL 1021 // other values, error using inSource 1022 // --------------------------------------------------------------- 1023 status_t 1024 BTranslatorRoster::Translate(BPositionIO *inSource, 1025 const translator_info *inInfo, BMessage *ioExtension, 1026 BPositionIO *outDestination, uint32 inWantOutType, 1027 uint32 inHintType, const char *inHintMIME) 1028 { 1029 if (!inSource || !outDestination) 1030 return B_BAD_VALUE; 1031 1032 if (fSem <= 0) 1033 return B_NOT_INITIALIZED; 1034 1035 status_t result = B_OK; 1036 translator_info stat_info; 1037 1038 if (!inInfo) { 1039 // go look for a suitable translator 1040 inInfo = &stat_info; 1041 1042 result = Identify(inSource, ioExtension, &stat_info, 1043 inHintType, inHintMIME, inWantOutType); 1044 // Identify is a locked function, so it cannot be 1045 // called from code that is already locked 1046 } 1047 1048 if (result >= B_OK && acquire_sem(fSem) == B_OK) { 1049 translator_node *pTranNode = FindTranslatorNode(inInfo->translator); 1050 if (!pTranNode) { 1051 result = B_NO_TRANSLATOR; 1052 } 1053 else { 1054 result = inSource->Seek(0, SEEK_SET); 1055 if (result == B_OK) 1056 result = pTranNode->translator->Translate(inSource, inInfo, 1057 ioExtension, inWantOutType, outDestination); 1058 } 1059 release_sem(fSem); 1060 } 1061 1062 return result; 1063 } 1064 1065 // --------------------------------------------------------------- 1066 // Translate 1067 // 1068 // This function is the whole point of the Translation Kit. 1069 // This is for translating the data in inSource to outDestination 1070 // using the format inWantOutType. 1071 // 1072 // Preconditions: 1073 // 1074 // Parameters: inSource, the data that wants to be translated 1075 // ioExtension, configuration data for the translator 1076 // inTranslator, the translator to use for the 1077 // translation 1078 // inWantOutType, the desired output type for 1079 // the data in inSource. 1080 // outDestination, where inSource is translated to 1081 // 1082 // Postconditions: 1083 // 1084 // Returns: B_OK, translation successful, 1085 // B_NO_TRANSLATOR, inTranslator is an invalid id 1086 // B_NOT_INITIALIZED, the constructor failed to 1087 // create a semaphore 1088 // B_BAD_VALUE, inSource or outDestination is NULL 1089 // other values, error using inSource 1090 // --------------------------------------------------------------- 1091 status_t 1092 BTranslatorRoster::Translate(translator_id inTranslator, 1093 BPositionIO *inSource, BMessage *ioExtension, 1094 BPositionIO *outDestination, uint32 inWantOutType) 1095 { 1096 if (!inSource || !outDestination) 1097 return B_BAD_VALUE; 1098 1099 status_t result = B_NOT_INITIALIZED; 1100 1101 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1102 translator_node *pTranNode = FindTranslatorNode(inTranslator); 1103 if (!pTranNode) 1104 result = B_NO_TRANSLATOR; 1105 else { 1106 result = inSource->Seek(0, SEEK_SET); 1107 if (result == B_OK) { 1108 translator_info traninfo; 1109 result = pTranNode->translator->Identify(inSource, NULL, 1110 ioExtension, &traninfo, inWantOutType); 1111 if (result == B_OK) { 1112 result = inSource->Seek(0, SEEK_SET); 1113 if (result == B_OK) { 1114 result = pTranNode->translator->Translate(inSource, 1115 &traninfo, ioExtension, inWantOutType, 1116 outDestination); 1117 } 1118 } 1119 } 1120 } 1121 release_sem(fSem); 1122 } 1123 1124 return result; 1125 } 1126 1127 // --------------------------------------------------------------- 1128 // MakeConfigurationView 1129 // 1130 // Returns outView, a BView for configuring the translator 1131 // forTranslator. Not all translators support this. 1132 // 1133 // Preconditions: 1134 // 1135 // Parameters: forTranslator, the translator the view is for 1136 // ioExtension, the configuration data for 1137 // the translator 1138 // outView, the view for configuring the 1139 // translator 1140 // outExtent, the bounds for the view, the view 1141 // can be resized 1142 // 1143 // Postconditions: 1144 // 1145 // Returns: B_OK, success, 1146 // B_NO_TRANSLATOR, inTranslator is an invalid id 1147 // B_NOT_INITIALIZED, the constructor failed to 1148 // create a semaphore 1149 // B_BAD_VALUE, inSource or outDestination is NULL 1150 // other values, error using inSource 1151 // --------------------------------------------------------------- 1152 status_t 1153 BTranslatorRoster::MakeConfigurationView( 1154 translator_id forTranslator, BMessage *ioExtension, 1155 BView **outView, BRect *outExtent) 1156 { 1157 if (!outView || !outExtent) 1158 return B_BAD_VALUE; 1159 1160 status_t result = B_NOT_INITIALIZED; 1161 1162 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1163 translator_node *pTranNode = FindTranslatorNode(forTranslator); 1164 if (!pTranNode) 1165 result = B_NO_TRANSLATOR; 1166 else 1167 result = pTranNode->translator->MakeConfigurationView(ioExtension, 1168 outView, outExtent); 1169 1170 release_sem(fSem); 1171 } 1172 1173 return result; 1174 } 1175 1176 // --------------------------------------------------------------- 1177 // GetConfigurationMessage 1178 // 1179 // Gets the configuration setttings for the translator 1180 // forTranslator and puts the settings into ioExtension. 1181 // 1182 // Preconditions: 1183 // 1184 // Parameters: forTranslator, the translator the info 1185 // is for 1186 // ioExtension, the configuration data for 1187 // the translator is stored here 1188 // 1189 // Postconditions: 1190 // 1191 // Returns: B_OK, success, 1192 // B_NO_TRANSLATOR, inTranslator is an invalid id 1193 // B_NOT_INITIALIZED, the constructor failed to 1194 // create a semaphore 1195 // B_BAD_VALUE, inSource or outDestination is NULL 1196 // other values, error using inSource 1197 // --------------------------------------------------------------- 1198 status_t 1199 BTranslatorRoster::GetConfigurationMessage( 1200 translator_id forTranslator, BMessage *ioExtension) 1201 { 1202 if (!ioExtension) 1203 return B_BAD_VALUE; 1204 1205 status_t result = B_NOT_INITIALIZED; 1206 1207 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1208 translator_node *pTranNode = FindTranslatorNode(forTranslator); 1209 if (!pTranNode) 1210 result = B_NO_TRANSLATOR; 1211 else 1212 result = 1213 pTranNode->translator->GetConfigurationMessage(ioExtension); 1214 1215 release_sem(fSem); 1216 } 1217 1218 return result; 1219 } 1220 1221 // --------------------------------------------------------------- 1222 // GetRefFor 1223 // 1224 // Gets the entry_ref for the given translator. 1225 // 1226 // Preconditions: 1227 // 1228 // Parameters: forTranslator, the translator the info 1229 // is for 1230 // entry_ref, where the entry ref is stored 1231 // 1232 // Postconditions: 1233 // 1234 // Returns: B_OK, success, 1235 // B_NO_TRANSLATOR, translator is an invalid id 1236 // B_NOT_INITIALIZED, the constructor failed to 1237 // create a semaphore 1238 // B_BAD_VALUE, inSource or outDestination is NULL 1239 // other values, error using inSource 1240 // --------------------------------------------------------------- 1241 status_t 1242 BTranslatorRoster::GetRefFor(translator_id translator, 1243 entry_ref *out_ref) 1244 { 1245 if (!out_ref) 1246 return B_BAD_VALUE; 1247 1248 status_t result = B_NOT_INITIALIZED; 1249 1250 if (fSem > 0 && acquire_sem(fSem) == B_OK) { 1251 translator_node *pTranNode = FindTranslatorNode(translator); 1252 if (!pTranNode) 1253 result = B_NO_TRANSLATOR; 1254 else { 1255 if (pTranNode->path[0] == '\0') 1256 result = B_ERROR; 1257 else 1258 result = get_ref_for_path(pTranNode->path, out_ref); 1259 } 1260 release_sem(fSem); 1261 } 1262 1263 return result; 1264 } 1265 1266 1267 // --------------------------------------------------------------- 1268 // FindTranslatorNode 1269 // 1270 // Finds the translator_node that holds the translator with 1271 // the translator_id id. 1272 // 1273 // Preconditions: 1274 // 1275 // Parameters: id, the translator you want a translator_node for 1276 // 1277 // Postconditions: 1278 // 1279 // Returns: NULL if id is not a valid translator_id, 1280 // pointer to the translator_node that holds the 1281 // translator id 1282 // --------------------------------------------------------------- 1283 translator_node * 1284 BTranslatorRoster::FindTranslatorNode(translator_id id) 1285 { 1286 translator_node *pTranNode = NULL; 1287 for (pTranNode = fpTranslators; pTranNode; pTranNode = pTranNode->next) 1288 if (pTranNode->id == id) 1289 break; 1290 1291 return pTranNode; 1292 } 1293 1294 // --------------------------------------------------------------- 1295 // LoadTranslator 1296 // 1297 // Loads the translator from path into memory and adds it to 1298 // the BTranslatorRoster. 1299 // 1300 // Preconditions: This should only be called inside of locked 1301 // code. 1302 // 1303 // Parameters: path, the path for the translator to be loaded 1304 // 1305 // Postconditions: 1306 // 1307 // Returns: B_BAD_VALUE, if path is NULL, 1308 // B_NO_ERROR, if all is well, 1309 // other values if error loading add ons 1310 // --------------------------------------------------------------- 1311 status_t 1312 BTranslatorRoster::LoadTranslator(const char *path) 1313 { 1314 if (!path) 1315 return B_BAD_VALUE; 1316 1317 // check that this ref is not already loaded 1318 const char *name = strrchr(path, '/'); 1319 if (name) 1320 name++; 1321 else 1322 name = path; 1323 for (translator_node *i = fpTranslators; i; i = i->next) 1324 if (!strcmp(name, i->translator->TranslatorName())) 1325 return B_NO_ERROR; 1326 // we use name for determining whether it's loaded 1327 // that is not entirely foolproof, but making SURE will be 1328 // a very slow process that I don't much care for. 1329 1330 image_id image = load_add_on(path); 1331 // Load the data and code for the Translator into memory 1332 if (image < 0) 1333 return image; 1334 1335 // Function pointer used to create post R4.5 style translators 1336 BTranslator *(*pMakeNthTranslator)(int32 n, image_id you, uint32 flags, ...); 1337 1338 status_t err = get_image_symbol(image, "make_nth_translator", 1339 B_SYMBOL_TYPE_TEXT, reinterpret_cast<void **> (&pMakeNthTranslator)); 1340 if (!err) { 1341 // If the translator add-on supports the post R4.5 1342 // translator creation mechanism 1343 1344 BTranslator *ptran = NULL; 1345 // WARNING: This code assumes that the ref count on the 1346 // BTranslators from MakeNth... begin at 1!!! 1347 // I NEED TO WRITE CODE TO TEST WHAT THE REF COUNT FOR 1348 // THESE BTRANSLATORS START AS!!!! 1349 for (int32 n = 0; (ptran = pMakeNthTranslator(n, image, 0)); n++) 1350 AddTranslatorToList(ptran, path, image, false); 1351 1352 return B_NO_ERROR; 1353 1354 } else { 1355 // If the translator add-on is in the R4.0 / R4.5 format 1356 translator_data trand; 1357 trand.translatorName = NULL; 1358 trand.translatorInfo = NULL; 1359 trand.translatorVersion = 0; 1360 trand.inputFormats = NULL; 1361 trand.outputFormats = NULL; 1362 trand.Identify = NULL; 1363 trand.Translate = NULL; 1364 trand.MakeConfig = NULL; 1365 trand.GetConfigMessage = NULL; 1366 1367 char *name = NULL, *info = NULL; 1368 translation_format *ins = NULL, *outs = NULL; 1369 1370 // find all the symbols 1371 err = get_image_symbol(image, "translatorName", B_SYMBOL_TYPE_DATA, 1372 reinterpret_cast<void **> (&name)); 1373 if (err) 1374 name = NULL; 1375 else if (!err && get_image_symbol(image, "translatorInfo", 1376 B_SYMBOL_TYPE_DATA, reinterpret_cast<void **> (&info))) 1377 info = NULL; 1378 1379 int32 *pn = NULL; 1380 if (!err) { 1381 err = get_image_symbol(image, "translatorVersion", 1382 B_SYMBOL_TYPE_DATA, reinterpret_cast<void **> (&pn)); 1383 if (!err && (pn != NULL)) 1384 trand.translatorVersion = *pn; 1385 } 1386 1387 if (!err && get_image_symbol(image, "inputFormats", 1388 B_SYMBOL_TYPE_DATA, 1389 reinterpret_cast<void **> (&ins))) 1390 ins = NULL; 1391 1392 if (!err && get_image_symbol(image, "outputFormats", 1393 B_SYMBOL_TYPE_DATA, 1394 reinterpret_cast<void **> (&outs))) 1395 outs = NULL; 1396 1397 if (!err) 1398 err = get_image_symbol(image, "Identify", 1399 B_SYMBOL_TYPE_TEXT, 1400 reinterpret_cast<void **> (&trand.Identify)); 1401 1402 if (!err) 1403 err = get_image_symbol(image, "Translate", 1404 B_SYMBOL_TYPE_TEXT, 1405 reinterpret_cast<void **> (&trand.Translate)); 1406 1407 if (!err && get_image_symbol(image, "MakeConfig", 1408 B_SYMBOL_TYPE_TEXT, 1409 reinterpret_cast<void **> (&trand.MakeConfig))) 1410 trand.MakeConfig = NULL; 1411 1412 if (!err && get_image_symbol(image, "GetConfigMessage", 1413 B_SYMBOL_TYPE_TEXT, 1414 reinterpret_cast<void **> (&trand.GetConfigMessage))) 1415 trand.GetConfigMessage = NULL; 1416 1417 trand.translatorName = name; 1418 trand.translatorInfo = info; 1419 trand.inputFormats = ins; 1420 trand.outputFormats = outs; 1421 1422 // if add-on is not in the correct format, return with error 1423 if (err) 1424 return err; 1425 1426 // add this translator to the list 1427 BR4xTranslator *pR4xTran = new BR4xTranslator(&trand); 1428 AddTranslatorToList(pR4xTran, path, image, false); 1429 // do not call Acquire() on ptran because I want it to be 1430 // deleted the first time Release() is called on it. 1431 1432 return B_NO_ERROR; 1433 } 1434 } 1435 1436 // --------------------------------------------------------------- 1437 // LoadDir 1438 // 1439 // Loads all of the translators in the directory path 1440 // 1441 // Preconditions: should only be called inside locked code 1442 // 1443 // Parameters: path, the directory of translators to load 1444 // loadErr, the return code 1445 // nLoaded, number of translators loaded 1446 // 1447 // Postconditions: 1448 // 1449 // Returns: B_FILE_NOT_FOUND, if the path is NULL or invalid 1450 // other errors if LoadTranslator failed 1451 // --------------------------------------------------------------- 1452 void 1453 BTranslatorRoster::LoadDir(const char *path, int32 &loadErr, int32 &nLoaded) 1454 { 1455 if (!path) { 1456 loadErr = B_FILE_NOT_FOUND; 1457 return; 1458 } 1459 1460 loadErr = B_OK; 1461 DIR *dir = opendir(path); 1462 if (!dir) { 1463 loadErr = B_FILE_NOT_FOUND; 1464 return; 1465 } 1466 struct dirent *dent; 1467 struct stat stbuf; 1468 char cwd[PATH_MAX] = ""; 1469 while (NULL != (dent = readdir(dir))) { 1470 strcpy(cwd, path); 1471 strcat(cwd, "/"); 1472 strcat(cwd, dent->d_name); 1473 status_t err = stat(cwd, &stbuf); 1474 1475 if (!err && S_ISREG(stbuf.st_mode) && 1476 strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { 1477 1478 err = LoadTranslator(cwd); 1479 if (err == B_OK) 1480 nLoaded++; 1481 else 1482 loadErr = err; 1483 } 1484 } 1485 closedir(dir); 1486 } 1487 1488 // --------------------------------------------------------------- 1489 // CheckFormats 1490 // 1491 // Function used to determine if hintType and hintMIME can be 1492 // used to find the desired translation_format. 1493 // 1494 // Preconditions: Should only be called from inside locked code 1495 // 1496 // Parameters: inputFormats, the formats check against the hints 1497 // inputFormatsCount, number of items in inputFormats 1498 // hintType, the type this function is looking for 1499 // hintMIME, the MIME type this function is looking 1500 // for 1501 // outFormat, NULL if no suitable translation_format 1502 // from inputFormats was found, not NULL 1503 // if a translation_format matching the 1504 // hints was found 1505 // 1506 // 1507 // Postconditions: 1508 // 1509 // Returns: true, if a determination could be made 1510 // false, if indentification must be done 1511 // --------------------------------------------------------------- 1512 bool 1513 BTranslatorRoster::CheckFormats(const translation_format *inputFormats, 1514 int32 inputFormatsCount, uint32 hintType, const char *hintMIME, 1515 const translation_format **outFormat) 1516 { 1517 if (!inputFormats || inputFormatsCount <= 0 || !outFormat) 1518 return false; 1519 1520 *outFormat = NULL; 1521 1522 // return false if we can't use hints for this module 1523 if (!hintType && !hintMIME) 1524 return false; 1525 1526 // check for the length of the MIME string, since it may be just a prefix 1527 // so we use strncmp(). 1528 int mlen = 0; 1529 if (hintMIME) 1530 mlen = strlen(hintMIME); 1531 1532 // scan for suitable format 1533 const translation_format *fmt = inputFormats; 1534 for (int32 i = 0; i < inputFormatsCount && fmt->type; i++, fmt++) { 1535 if ((fmt->type == hintType) || 1536 (hintMIME && mlen && !strncmp(fmt->MIME, hintMIME, mlen))) { 1537 *outFormat = fmt; 1538 return true; 1539 } 1540 } 1541 // the module did export formats, but none matched. 1542 // we return true (uses formats) but set outFormat to NULL 1543 return true; 1544 } 1545 1546 // --------------------------------------------------------------- 1547 // AddTranslatorToList 1548 // 1549 // Adds a BTranslator based object to the list of translators 1550 // stored by the BTranslatorRoster. 1551 // 1552 // Preconditions: Should only be called inside locked code 1553 // 1554 // Parameters: translator, the translator to add to this object 1555 // 1556 // Postconditions: 1557 // 1558 // Returns: B_BAD_VALUE, if translator is NULL 1559 // B_OK, if not 1560 // --------------------------------------------------------------- 1561 status_t 1562 BTranslatorRoster::AddTranslatorToList(BTranslator *translator) 1563 { 1564 return AddTranslatorToList(translator, "", -1, true); 1565 // add translator to list with no add-on image to unload, 1566 // and call Acquire() on it 1567 } 1568 1569 // --------------------------------------------------------------- 1570 // AddTranslatorToList 1571 // 1572 // Adds a BTranslator based object to the list of translators 1573 // stored by the BTranslatorRoster. 1574 // 1575 // Preconditions: Should only be called inside locked code 1576 // 1577 // Parameters: translator, the translator to add to this object 1578 // path, the path the translator was loaded from 1579 // image, the image the translator was loaded from 1580 // acquire, if true Acquire() is called on the 1581 // translator 1582 // 1583 // Postconditions: 1584 // 1585 // Returns: B_BAD_VALUE, if translator is NULL 1586 // B_OK, if not 1587 // --------------------------------------------------------------- 1588 status_t 1589 BTranslatorRoster::AddTranslatorToList(BTranslator *translator, 1590 const char *path, image_id image, bool acquire) 1591 { 1592 if (!translator || !path) 1593 return B_BAD_VALUE; 1594 1595 translator_node *pTranNode = new translator_node; 1596 1597 if (acquire) 1598 pTranNode->translator = translator->Acquire(); 1599 else 1600 pTranNode->translator = translator; 1601 1602 if (fpTranslators) 1603 pTranNode->id = fpTranslators->id + 1; 1604 else 1605 pTranNode->id = 1; 1606 1607 pTranNode->path = new char[strlen(path) + 1]; 1608 strcpy(pTranNode->path, path); 1609 pTranNode->image = image; 1610 pTranNode->next = fpTranslators; 1611 fpTranslators = pTranNode; 1612 1613 return B_OK; 1614 } 1615 1616 // --------------------------------------------------------------- 1617 // ReservedTranslatorRoster1 1618 // 1619 // It does nothing! :) Its here only for past/future binary 1620 // compatibility. 1621 // 1622 // Preconditions: 1623 // 1624 // Parameters: 1625 // 1626 // Postconditions: 1627 // 1628 // Returns: 1629 // --------------------------------------------------------------- 1630 void 1631 BTranslatorRoster::ReservedTranslatorRoster1() 1632 { 1633 } 1634 1635 // --------------------------------------------------------------- 1636 // ReservedTranslatorRoster2 1637 // 1638 // It does nothing! :) Its here only for past/future binary 1639 // compatibility. 1640 // 1641 // Preconditions: 1642 // 1643 // Parameters: 1644 // 1645 // Postconditions: 1646 // 1647 // Returns: 1648 // --------------------------------------------------------------- 1649 void 1650 BTranslatorRoster::ReservedTranslatorRoster2() 1651 { 1652 } 1653 1654 // --------------------------------------------------------------- 1655 // ReservedTranslatorRoster3 1656 // 1657 // It does nothing! :) Its here only for past/future binary 1658 // compatibility. 1659 // 1660 // Preconditions: 1661 // 1662 // Parameters: 1663 // 1664 // Postconditions: 1665 // 1666 // Returns: 1667 // --------------------------------------------------------------- 1668 void 1669 BTranslatorRoster::ReservedTranslatorRoster3() 1670 { 1671 } 1672 1673 // --------------------------------------------------------------- 1674 // ReservedTranslatorRoster4 1675 // 1676 // It does nothing! :) Its here only for past/future binary 1677 // compatibility. 1678 // 1679 // Preconditions: 1680 // 1681 // Parameters: 1682 // 1683 // Postconditions: 1684 // 1685 // Returns: 1686 // --------------------------------------------------------------- 1687 void 1688 BTranslatorRoster::ReservedTranslatorRoster4() 1689 { 1690 } 1691 1692 // --------------------------------------------------------------- 1693 // ReservedTranslatorRoster5 1694 // 1695 // It does nothing! :) Its here only for past/future binary 1696 // compatibility. 1697 // 1698 // Preconditions: 1699 // 1700 // Parameters: 1701 // 1702 // Postconditions: 1703 // 1704 // Returns: 1705 // --------------------------------------------------------------- 1706 void 1707 BTranslatorRoster::ReservedTranslatorRoster5() 1708 { 1709 } 1710 1711 // --------------------------------------------------------------- 1712 // ReservedTranslatorRoster6 1713 // 1714 // It does nothing! :) Its here only for past/future binary 1715 // compatibility. 1716 // 1717 // Preconditions: 1718 // 1719 // Parameters: 1720 // 1721 // Postconditions: 1722 // 1723 // Returns: 1724 // --------------------------------------------------------------- 1725 void 1726 BTranslatorRoster::ReservedTranslatorRoster6() 1727 { 1728 } 1729 1730