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