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