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