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