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