1 /* 2 * Copyright 2001-2009, Haiku. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * I.R. Adema 7 * Stefano Ceccherini (burton666@libero.it) 8 * Michael Pfeiffer 9 * julun <host.haiku@gmx.de> 10 */ 11 12 13 #include <PrintJob.h> 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include <Alert.h> 20 #include <Application.h> 21 #include <Button.h> 22 #include <Catalog.h> 23 #include <Debug.h> 24 #include <Entry.h> 25 #include <File.h> 26 #include <FindDirectory.h> 27 #include <LocaleBackend.h> 28 #include <Messenger.h> 29 #include <NodeInfo.h> 30 #include <OS.h> 31 #include <Path.h> 32 #include <Region.h> 33 #include <Roster.h> 34 #include <View.h> 35 36 #include <pr_server.h> 37 #include <ViewPrivate.h> 38 39 using BPrivate::gLocaleBackend; 40 using BPrivate::LocaleBackend; 41 42 #undef B_TRANSLATE_CONTEXT 43 #define B_TRANSLATE_CONTEXT "PrintJob" 44 45 #undef B_TRANSLATE 46 #define B_TRANSLATE(str) \ 47 gLocaleBackend->GetString(B_TRANSLATE_MARK(str), "PrintJob") 48 49 50 /*! Summary of spool file: 51 52 |-----------------------------------| 53 | print_file_header | 54 |-----------------------------------| 55 | BMessage print_job_settings | 56 |-----------------------------------| 57 | | 58 | ********** (first page) ********* | 59 | * * | 60 | * _page_header_ * | 61 | * ----------------------------- * | 62 | * |---------------------------| * | 63 | * | BPoint where | * | 64 | * | BRect bounds | * | 65 | * | BPicture pic | * | 66 | * |---------------------------| * | 67 | * |---------------------------| * | 68 | * | BPoint where | * | 69 | * | BRect bounds | * | 70 | * | BPicture pic | * | 71 | * |---------------------------| * | 72 | ********************************* | 73 | | 74 | ********* (second page) ********* | 75 | * * | 76 | * _page_header_ * | 77 | * ----------------------------- * | 78 | * |---------------------------| * | 79 | * | BPoint where | * | 80 | * | BRect bounds | * | 81 | * | BPicture pic | * | 82 | * |---------------------------| * | 83 | ********************************* | 84 |-----------------------------------| 85 86 BeOS R5 print_file_header.version is 1 << 16 87 BeOS R5 print_file_header.first_page is -1 88 89 each page can consist of a collection of picture structures 90 remaining pages start at _page_header_.next_page of previous _page_header_ 91 92 See also: "How to Write a BeOS R5 Printer Driver" for description of spool 93 file format: http://haiku-os.org/documents/dev/how_to_write_a_printer_driver 94 */ 95 96 97 struct _page_header_ { 98 int32 number_of_pictures; 99 off_t next_page; 100 int32 reserved[10]; 101 }; 102 103 104 static void 105 ShowError(const char* message) 106 { 107 BAlert* alert = new BAlert(B_TRANSLATE("Error"), message, B_TRANSLATE("OK")); 108 alert->Go(); 109 } 110 111 112 // #pragma mark -- PrintServerMessenger 113 114 115 namespace BPrivate { 116 117 118 class PrintServerMessenger { 119 public: 120 PrintServerMessenger(uint32 what, BMessage* input); 121 ~PrintServerMessenger(); 122 123 BMessage* Request(); 124 status_t SendRequest(); 125 126 void SetResult(BMessage* result); 127 BMessage* Result() const { return fResult; } 128 129 static status_t GetPrintServerMessenger(BMessenger& messenger); 130 131 private: 132 void RejectUserInput(); 133 void AllowUserInput(); 134 void DeleteSemaphore(); 135 static status_t MessengerThread(void* data); 136 137 uint32 fWhat; 138 BMessage* fInput; 139 BMessage* fRequest; 140 BMessage* fResult; 141 sem_id fThreadCompleted; 142 BAlert* fHiddenApplicationModalWindow; 143 }; 144 145 146 } // namespace BPrivate 147 148 149 using namespace BPrivate; 150 151 152 // #pragma mark -- BPrintJob 153 154 155 BPrintJob::BPrintJob(const char* jobName) 156 : 157 fPrintJobName(NULL), 158 fSpoolFile(NULL), 159 fError(B_NO_INIT), 160 fSetupMessage(NULL), 161 fDefaultSetupMessage(NULL), 162 fAbort(0), 163 fCurrentPageHeader(NULL) 164 { 165 memset(&fSpoolFileHeader, 0, sizeof(print_file_header)); 166 167 if (jobName != NULL && jobName[0]) 168 fPrintJobName = strdup(jobName); 169 170 fCurrentPageHeader = new _page_header_; 171 if (fCurrentPageHeader != NULL) 172 memset(fCurrentPageHeader, 0, sizeof(_page_header_)); 173 174 // we need to translate some strings, and in order to do so, we need 175 // to use the LocaleBackend to reach liblocale.so 176 if (gLocaleBackend == NULL) 177 LocaleBackend::LoadBackend(); 178 } 179 180 181 BPrintJob::~BPrintJob() 182 { 183 CancelJob(); 184 185 free(fPrintJobName); 186 delete fSetupMessage; 187 delete fDefaultSetupMessage; 188 delete fCurrentPageHeader; 189 } 190 191 192 status_t 193 BPrintJob::ConfigPage() 194 { 195 PrintServerMessenger messenger(PSRV_SHOW_PAGE_SETUP, fSetupMessage); 196 status_t status = messenger.SendRequest(); 197 if (status != B_OK) 198 return status; 199 200 delete fSetupMessage; 201 fSetupMessage = messenger.Result(); 202 _HandlePageSetup(fSetupMessage); 203 204 return B_OK; 205 } 206 207 208 status_t 209 BPrintJob::ConfigJob() 210 { 211 PrintServerMessenger messenger(PSRV_SHOW_PRINT_SETUP, fSetupMessage); 212 status_t status = messenger.SendRequest(); 213 if (status != B_OK) 214 return status; 215 216 delete fSetupMessage; 217 fSetupMessage = messenger.Result(); 218 if (!_HandlePrintSetup(fSetupMessage)) 219 return B_ERROR; 220 221 fError = B_OK; 222 return B_OK; 223 } 224 225 226 void 227 BPrintJob::BeginJob() 228 { 229 fError = B_ERROR; 230 231 // can not start a new job until it has been commited or cancelled 232 if (fSpoolFile != NULL || fCurrentPageHeader == NULL) 233 return; 234 235 // TODO show alert, setup message is required 236 if (fSetupMessage == NULL) 237 return; 238 239 // create spool file 240 BPath path; 241 status_t status = find_directory(B_USER_PRINTERS_DIRECTORY, &path); 242 if (status != B_OK) 243 return; 244 245 char *printer = _GetCurrentPrinterName(); 246 if (printer == NULL) 247 return; 248 249 path.Append(printer); 250 free(printer); 251 252 char mangledName[B_FILE_NAME_LENGTH]; 253 _GetMangledName(mangledName, B_FILE_NAME_LENGTH); 254 255 path.Append(mangledName); 256 if (path.InitCheck() != B_OK) 257 return; 258 259 // TODO: fSpoolFileName should store the name only (not path which can be 260 // 1024 bytes long) 261 strlcpy(fSpoolFileName, path.Path(), sizeof(fSpoolFileName)); 262 fSpoolFile = new BFile(fSpoolFileName, B_READ_WRITE | B_CREATE_FILE); 263 264 if (fSpoolFile->InitCheck() != B_OK) { 265 CancelJob(); 266 return; 267 } 268 269 // add print_file_header 270 // page_count is updated in CommitJob() 271 // on BeOS R5 the offset to the first page was always -1 272 fSpoolFileHeader.version = 1 << 16; 273 fSpoolFileHeader.page_count = 0; 274 fSpoolFileHeader.first_page = (off_t)-1; 275 276 if (fSpoolFile->Write(&fSpoolFileHeader, sizeof(print_file_header)) 277 != sizeof(print_file_header)) { 278 CancelJob(); 279 return; 280 } 281 282 // add printer settings message 283 if (!fSetupMessage->HasString(PSRV_FIELD_CURRENT_PRINTER)) 284 fSetupMessage->AddString(PSRV_FIELD_CURRENT_PRINTER, printer); 285 286 _AddSetupSpec(); 287 _NewPage(); 288 289 // state variables 290 fAbort = 0; 291 fError = B_OK; 292 } 293 294 295 void 296 BPrintJob::CommitJob() 297 { 298 if (fSpoolFile == NULL) 299 return; 300 301 if (fSpoolFileHeader.page_count == 0) { 302 ShowError(B_TRANSLATE("No Pages to print!")); 303 CancelJob(); 304 return; 305 } 306 307 // update spool file 308 _EndLastPage(); 309 310 // write spool file header 311 fSpoolFile->Seek(0, SEEK_SET); 312 fSpoolFile->Write(&fSpoolFileHeader, sizeof(print_file_header)); 313 314 // set file attributes 315 app_info appInfo; 316 be_app->GetAppInfo(&appInfo); 317 const char* printerName = ""; 318 fSetupMessage->FindString(PSRV_FIELD_CURRENT_PRINTER, &printerName); 319 320 BNodeInfo info(fSpoolFile); 321 info.SetType(PSRV_SPOOL_FILETYPE); 322 323 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PAGECOUNT, B_INT32_TYPE, 0, 324 &fSpoolFileHeader.page_count, sizeof(int32)); 325 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_DESCRIPTION, B_STRING_TYPE, 0, 326 fPrintJobName, strlen(fPrintJobName) + 1); 327 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PRINTER, B_STRING_TYPE, 0, 328 printerName, strlen(printerName) + 1); 329 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, 330 PSRV_JOB_STATUS_WAITING, strlen(PSRV_JOB_STATUS_WAITING) + 1); 331 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_MIMETYPE, B_STRING_TYPE, 0, 332 appInfo.signature, strlen(appInfo.signature) + 1); 333 334 delete fSpoolFile; 335 fSpoolFile = NULL; 336 fError = B_ERROR; 337 338 // notify print server 339 BMessenger printServer; 340 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 341 return; 342 343 BMessage request(PSRV_PRINT_SPOOLED_JOB); 344 request.AddString("JobName", fPrintJobName); 345 request.AddString("Spool File", fSpoolFileName); 346 347 BMessage reply; 348 printServer.SendMessage(&request, &reply); 349 } 350 351 352 void 353 BPrintJob::CancelJob() 354 { 355 if (fSpoolFile == NULL) 356 return; 357 358 fAbort = 1; 359 BEntry(fSpoolFileName).Remove(); 360 delete fSpoolFile; 361 fSpoolFile = NULL; 362 } 363 364 365 void 366 BPrintJob::SpoolPage() 367 { 368 if (fSpoolFile == NULL) 369 return; 370 371 if (fCurrentPageHeader->number_of_pictures == 0) 372 return; 373 374 fSpoolFileHeader.page_count++; 375 fSpoolFile->Seek(0, SEEK_END); 376 if (fCurrentPageHeaderOffset) { 377 // update last written page_header 378 fCurrentPageHeader->next_page = fSpoolFile->Position(); 379 fSpoolFile->Seek(fCurrentPageHeaderOffset, SEEK_SET); 380 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_)); 381 fSpoolFile->Seek(fCurrentPageHeader->next_page, SEEK_SET); 382 } 383 384 _NewPage(); 385 } 386 387 388 bool 389 BPrintJob::CanContinue() 390 { 391 // Check if our local error storage is still B_OK 392 return fError == B_OK && !fAbort; 393 } 394 395 396 void 397 BPrintJob::DrawView(BView* view, BRect rect, BPoint where) 398 { 399 if (fSpoolFile == NULL) 400 return; 401 402 if (view == NULL) 403 return; 404 405 if (view->LockLooper()) { 406 BPicture picture; 407 _RecurseView(view, B_ORIGIN - rect.LeftTop(), &picture, rect); 408 _AddPicture(picture, rect, where); 409 view->UnlockLooper(); 410 } 411 } 412 413 414 BMessage* 415 BPrintJob::Settings() 416 { 417 if (fSetupMessage == NULL) 418 return NULL; 419 420 return new BMessage(*fSetupMessage); 421 } 422 423 424 void 425 BPrintJob::SetSettings(BMessage* message) 426 { 427 if (message != NULL) 428 _HandlePrintSetup(message); 429 430 delete fSetupMessage; 431 fSetupMessage = message; 432 } 433 434 435 bool 436 BPrintJob::IsSettingsMessageValid(BMessage* message) const 437 { 438 char* printerName = _GetCurrentPrinterName(); 439 if (printerName == NULL) 440 return false; 441 442 const char* name = NULL; 443 // The passed message is valid if it contains the right printer name. 444 bool valid = message != NULL 445 && message->FindString("printer_name", &name) == B_OK 446 && strcmp(printerName, name) == 0; 447 448 free(printerName); 449 return valid; 450 } 451 452 453 // Either SetSettings() or ConfigPage() has to be called prior 454 // to any of the getters otherwise they return undefined values. 455 BRect 456 BPrintJob::PaperRect() 457 { 458 if (fDefaultSetupMessage == NULL) 459 _LoadDefaultSettings(); 460 461 return fPaperSize; 462 } 463 464 465 BRect 466 BPrintJob::PrintableRect() 467 { 468 if (fDefaultSetupMessage == NULL) 469 _LoadDefaultSettings(); 470 471 return fUsableSize; 472 } 473 474 475 void 476 BPrintJob::GetResolution(int32* xdpi, int32* ydpi) 477 { 478 if (fDefaultSetupMessage == NULL) 479 _LoadDefaultSettings(); 480 481 if (xdpi != NULL) 482 *xdpi = fXResolution; 483 484 if (ydpi != NULL) 485 *ydpi = fYResolution; 486 } 487 488 489 int32 490 BPrintJob::FirstPage() 491 { 492 return fFirstPage; 493 } 494 495 496 int32 497 BPrintJob::LastPage() 498 { 499 return fLastPage; 500 } 501 502 503 int32 504 BPrintJob::PrinterType(void*) const 505 { 506 BMessenger printServer; 507 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 508 return B_COLOR_PRINTER; // default 509 510 BMessage reply; 511 BMessage message(PSRV_GET_ACTIVE_PRINTER); 512 printServer.SendMessage(&message, &reply); 513 514 int32 type; 515 if (reply.FindInt32("color", &type) != B_OK) 516 return B_COLOR_PRINTER; // default 517 518 return type; 519 } 520 521 522 // #pragma mark - private 523 524 525 void 526 BPrintJob::_RecurseView(BView* view, BPoint origin, BPicture* picture, 527 BRect rect) 528 { 529 ASSERT(picture != NULL); 530 531 BRegion region; 532 region.Set(BRect(rect.left, rect.top, rect.right, rect.bottom)); 533 view->fState->print_rect = rect; 534 535 view->AppendToPicture(picture); 536 view->PushState(); 537 view->SetOrigin(origin); 538 view->ConstrainClippingRegion(®ion); 539 540 if (view->ViewColor() != B_TRANSPARENT_COLOR) { 541 rgb_color highColor = view->HighColor(); 542 view->SetHighColor(view->ViewColor()); 543 view->FillRect(rect); 544 view->SetHighColor(highColor); 545 } 546 547 if ((view->Flags() & B_WILL_DRAW) != 0) { 548 view->fIsPrinting = true; 549 view->Draw(rect); 550 view->fIsPrinting = false; 551 } 552 553 view->PopState(); 554 view->EndPicture(); 555 556 BView* child = view->ChildAt(0); 557 while (child != NULL) { 558 if (!child->IsHidden()) { 559 BPoint leftTop(view->Bounds().LeftTop() + child->Frame().LeftTop()); 560 BRect printRect(rect.OffsetToCopy(rect.LeftTop() - leftTop) 561 & child->Bounds()); 562 if (printRect.IsValid()) 563 _RecurseView(child, origin + leftTop, picture, printRect); 564 } 565 child = child->NextSibling(); 566 } 567 568 if ((view->Flags() & B_DRAW_ON_CHILDREN) != 0) { 569 view->AppendToPicture(picture); 570 view->PushState(); 571 view->SetOrigin(origin); 572 view->ConstrainClippingRegion(®ion); 573 view->fIsPrinting = true; 574 view->DrawAfterChildren(rect); 575 view->fIsPrinting = false; 576 view->PopState(); 577 view->EndPicture(); 578 } 579 } 580 581 582 void 583 BPrintJob::_GetMangledName(char* buffer, size_t bufferSize) const 584 { 585 snprintf(buffer, bufferSize, "%s@%lld", fPrintJobName, 586 system_time() / 1000); 587 } 588 589 590 void 591 BPrintJob::_HandlePageSetup(BMessage* setup) 592 { 593 setup->FindRect(PSRV_FIELD_PRINTABLE_RECT, &fUsableSize); 594 setup->FindRect(PSRV_FIELD_PAPER_RECT, &fPaperSize); 595 596 // TODO verify data type (taken from libprint) 597 int64 valueInt64; 598 if (setup->FindInt64(PSRV_FIELD_XRES, &valueInt64) == B_OK) 599 fXResolution = (short)valueInt64; 600 601 if (setup->FindInt64(PSRV_FIELD_YRES, &valueInt64) == B_OK) 602 fYResolution = (short)valueInt64; 603 } 604 605 606 bool 607 BPrintJob::_HandlePrintSetup(BMessage* message) 608 { 609 _HandlePageSetup(message); 610 611 bool valid = true; 612 if (message->FindInt32(PSRV_FIELD_FIRST_PAGE, &fFirstPage) != B_OK) 613 valid = false; 614 615 if (message->FindInt32(PSRV_FIELD_LAST_PAGE, &fLastPage) != B_OK) 616 valid = false; 617 618 return valid; 619 } 620 621 622 void 623 BPrintJob::_NewPage() 624 { 625 // init, write new page_header 626 fCurrentPageHeader->next_page = 0; 627 fCurrentPageHeader->number_of_pictures = 0; 628 fCurrentPageHeaderOffset = fSpoolFile->Position(); 629 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_)); 630 } 631 632 633 void 634 BPrintJob::_EndLastPage() 635 { 636 if (!fSpoolFile) 637 return; 638 639 if (fCurrentPageHeader->number_of_pictures == 0) 640 return; 641 642 fSpoolFileHeader.page_count++; 643 fSpoolFile->Seek(0, SEEK_END); 644 if (fCurrentPageHeaderOffset) { 645 fCurrentPageHeader->next_page = 0; 646 fSpoolFile->Seek(fCurrentPageHeaderOffset, SEEK_SET); 647 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_)); 648 fSpoolFile->Seek(0, SEEK_END); 649 } 650 } 651 652 653 void 654 BPrintJob::_AddSetupSpec() 655 { 656 fSetupMessage->Flatten(fSpoolFile); 657 } 658 659 660 void 661 BPrintJob::_AddPicture(BPicture& picture, BRect& rect, BPoint& where) 662 { 663 ASSERT(fSpoolFile != NULL); 664 665 fCurrentPageHeader->number_of_pictures++; 666 fSpoolFile->Write(&where, sizeof(BRect)); 667 fSpoolFile->Write(&rect, sizeof(BPoint)); 668 picture.Flatten(fSpoolFile); 669 } 670 671 672 /*! Returns a copy of the applications default printer name or NULL if it 673 could not be obtained. Caller is responsible to free the string using 674 free(). 675 */ 676 char* 677 BPrintJob::_GetCurrentPrinterName() const 678 { 679 BMessenger printServer; 680 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 681 return NULL; 682 683 const char* printerName = NULL; 684 685 BMessage reply; 686 BMessage message(PSRV_GET_ACTIVE_PRINTER); 687 if (printServer.SendMessage(&message, &reply) == B_OK) 688 reply.FindString("printer_name", &printerName); 689 690 if (printerName == NULL) 691 return NULL; 692 693 return strdup(printerName); 694 } 695 696 697 void 698 BPrintJob::_LoadDefaultSettings() 699 { 700 BMessenger printServer; 701 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK) 702 return; 703 704 BMessage message(PSRV_GET_DEFAULT_SETTINGS); 705 BMessage* reply = new BMessage; 706 707 printServer.SendMessage(&message, reply); 708 709 // Only override our settings if we don't have any settings yet 710 if (fSetupMessage == NULL) 711 _HandlePrintSetup(reply); 712 713 delete fDefaultSetupMessage; 714 fDefaultSetupMessage = reply; 715 } 716 717 718 void BPrintJob::_ReservedPrintJob1() {} 719 void BPrintJob::_ReservedPrintJob2() {} 720 void BPrintJob::_ReservedPrintJob3() {} 721 void BPrintJob::_ReservedPrintJob4() {} 722 723 724 // #pragma mark -- PrintServerMessenger 725 726 727 namespace BPrivate { 728 729 730 PrintServerMessenger::PrintServerMessenger(uint32 what, BMessage *input) 731 : 732 fWhat(what), 733 fInput(input), 734 fRequest(NULL), 735 fResult(NULL), 736 fThreadCompleted(-1), 737 fHiddenApplicationModalWindow(NULL) 738 { 739 RejectUserInput(); 740 } 741 742 743 PrintServerMessenger::~PrintServerMessenger() 744 { 745 DeleteSemaphore(); 746 // in case SendRequest could not start the thread 747 delete fRequest; fRequest = NULL; 748 AllowUserInput(); 749 } 750 751 752 void 753 PrintServerMessenger::RejectUserInput() 754 { 755 fHiddenApplicationModalWindow = new BAlert("bogus", "app_modal", "OK"); 756 fHiddenApplicationModalWindow->DefaultButton()->SetEnabled(false); 757 fHiddenApplicationModalWindow->SetDefaultButton(NULL); 758 fHiddenApplicationModalWindow->MoveTo(-65000, -65000); 759 fHiddenApplicationModalWindow->Go(NULL); 760 } 761 762 763 void 764 PrintServerMessenger::AllowUserInput() 765 { 766 fHiddenApplicationModalWindow->Lock(); 767 fHiddenApplicationModalWindow->Quit(); 768 } 769 770 771 void 772 PrintServerMessenger::DeleteSemaphore() 773 { 774 if (fThreadCompleted >= B_OK) { 775 sem_id id = fThreadCompleted; 776 fThreadCompleted = -1; 777 delete_sem(id); 778 } 779 } 780 781 782 status_t 783 PrintServerMessenger::SendRequest() 784 { 785 fThreadCompleted = create_sem(0, "print_server_messenger_sem"); 786 if (fThreadCompleted < B_OK) 787 return B_ERROR; 788 789 thread_id id = spawn_thread(MessengerThread, "async_request", 790 B_NORMAL_PRIORITY, this); 791 if (id <= 0 || resume_thread(id) != B_OK) 792 return B_ERROR; 793 794 // Get the originating window, if it exists 795 BWindow* window = dynamic_cast<BWindow*>( 796 BLooper::LooperForThread(find_thread(NULL))); 797 if (window != NULL) { 798 status_t err; 799 while (true) { 800 do { 801 err = acquire_sem_etc(fThreadCompleted, 1, B_RELATIVE_TIMEOUT, 802 50000); 803 // We've (probably) had our time slice taken away from us 804 } while (err == B_INTERRUPTED); 805 806 // Semaphore was finally nuked in SetResult(BMessage *) 807 if (err == B_BAD_SEM_ID) 808 break; 809 window->UpdateIfNeeded(); 810 } 811 } else { 812 // No window to update, so just hang out until we're done. 813 while (acquire_sem(fThreadCompleted) == B_INTERRUPTED); 814 } 815 816 status_t status; 817 wait_for_thread(id, &status); 818 819 return Result() != NULL ? B_OK : B_ERROR; 820 } 821 822 823 BMessage* 824 PrintServerMessenger::Request() 825 { 826 if (fRequest != NULL) 827 return fRequest; 828 829 if (fInput != NULL) { 830 fRequest = new BMessage(*fInput); 831 fRequest->what = fWhat; 832 } else 833 fRequest = new BMessage(fWhat); 834 835 return fRequest; 836 } 837 838 839 void 840 PrintServerMessenger::SetResult(BMessage* result) 841 { 842 fResult = result; 843 DeleteSemaphore(); 844 // terminate loop in thread spawned by SendRequest 845 } 846 847 848 status_t 849 PrintServerMessenger::GetPrintServerMessenger(BMessenger& messenger) 850 { 851 messenger = BMessenger(PSRV_SIGNATURE_TYPE); 852 return messenger.IsValid() ? B_OK : B_ERROR; 853 } 854 855 856 status_t 857 PrintServerMessenger::MessengerThread(void* data) 858 { 859 PrintServerMessenger* messenger = static_cast<PrintServerMessenger*>(data); 860 861 BMessenger printServer; 862 if (messenger->GetPrintServerMessenger(printServer) != B_OK) { 863 ShowError(B_TRANSLATE("Print Server is not responding.")); 864 messenger->SetResult(NULL); 865 return B_ERROR; 866 } 867 868 BMessage* request = messenger->Request(); 869 if (request == NULL) { 870 messenger->SetResult(NULL); 871 return B_ERROR; 872 } 873 874 875 BMessage reply; 876 if (printServer.SendMessage(request, &reply) != B_OK 877 || reply.what != 'okok' ) { 878 messenger->SetResult(NULL); 879 return B_ERROR; 880 } 881 882 messenger->SetResult(new BMessage(reply)); 883 return B_OK; 884 } 885 886 887 } // namespace BPrivate 888