* update year in copyright
* added a bit more (visual) information about the spool file format
* rename Configuration to PrintServerMessenger (still not the best name)
* remove ConfigPage{Job}Thread as both share the same code and make it privte in PrintServerMessenger
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25966 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+244
-249
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2006, Haiku.
|
* Copyright 2001-2008, Haiku.
|
||||||
* Distributed under the terms of the MIT license.
|
* Distributed under the terms of the MIT license.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -9,8 +9,6 @@
|
|||||||
* julun <[email protected]>
|
* julun <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO refactor (avoid code duplications, decrease method sizes)
|
|
||||||
|
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <Button.h>
|
#include <Button.h>
|
||||||
@@ -36,27 +34,39 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
static const int kSemTimeOut = 50000;
|
/* !
|
||||||
static const char *kPrintServerNotRespondingText = "Print Server is not responding.";
|
*
|
||||||
static const char *kNoPagesToPrintText = "No Pages to print!";
|
* Summery of R5 spool file:
|
||||||
|
*
|
||||||
|
* |-------------------------|
|
||||||
|
* | print_file_header |
|
||||||
|
* |-------------------------|
|
||||||
|
* | BMessage |
|
||||||
|
* |-------------------------|
|
||||||
|
* | _page_header_ |
|
||||||
|
* | BPoint |
|
||||||
|
* | BRect |
|
||||||
|
* | BPicture |
|
||||||
|
* |-------------------------|
|
||||||
|
* | _page_header_ |
|
||||||
|
* | BPoint |
|
||||||
|
* | BRect |
|
||||||
|
* | BPicture |
|
||||||
|
* |-------------------------|
|
||||||
|
* | _page_header_ |
|
||||||
|
* |-------------------------|
|
||||||
|
*
|
||||||
|
* BeOS R5 print_file_header.version is 1 << 16
|
||||||
|
* BeOS R5 print_file_header.first_page is -1
|
||||||
|
*
|
||||||
|
* remaining pages start at _page_header_.next_page of previous _page_header_
|
||||||
|
*
|
||||||
|
* See also: "How to Write a BeOS R5 Printer Driver" for description of spool
|
||||||
|
* file format: http://haiku-os.org/documents/dev/how_to_write_a_printer_driver
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Summery of spool file format:
|
|
||||||
// See articel "How to Write a BeOS R5 Printer Driver" for description
|
|
||||||
// of spool file format:
|
|
||||||
// http://haiku-os.org/documents/dev/how_to_write_a_printer_driver
|
|
||||||
|
|
||||||
// print_file_header header
|
|
||||||
// On BeOS R5 header.version is 1 << 16 and
|
|
||||||
// header.first_page is -1.
|
|
||||||
// BMessage job_settings
|
|
||||||
// _page_header_ page_header
|
|
||||||
// followed by number_of_pictures:
|
|
||||||
// BPoint where
|
|
||||||
// BRect bounds
|
|
||||||
// BPicture picture
|
|
||||||
// remaining pages start at page_header.next_page of previous page_header
|
|
||||||
|
|
||||||
struct _page_header_ {
|
struct _page_header_ {
|
||||||
int32 number_of_pictures;
|
int32 number_of_pictures;
|
||||||
off_t next_page;
|
off_t next_page;
|
||||||
@@ -64,14 +74,6 @@ struct _page_header_ {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
GetPrinterServerMessenger(BMessenger& messenger)
|
|
||||||
{
|
|
||||||
messenger = BMessenger(PSRV_SIGNATURE_TYPE);
|
|
||||||
return messenger.IsValid() ? B_OK : B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ShowError(const char *message)
|
ShowError(const char *message)
|
||||||
{
|
{
|
||||||
@@ -80,155 +82,45 @@ ShowError(const char *message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -- PrintServerMessenger
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
class Configuration {
|
|
||||||
public:
|
|
||||||
Configuration(uint32 what, BMessage *input);
|
|
||||||
~Configuration();
|
|
||||||
|
|
||||||
status_t SendRequest(thread_func function);
|
class PrintServerMessenger {
|
||||||
|
public:
|
||||||
|
PrintServerMessenger(uint32 what, BMessage *input);
|
||||||
|
~PrintServerMessenger();
|
||||||
|
|
||||||
BMessage* Request();
|
BMessage* Request();
|
||||||
|
status_t SendRequest();
|
||||||
|
|
||||||
void SetResult(BMessage* result);
|
void SetResult(BMessage* result);
|
||||||
BMessage* Result() const { return fResult; }
|
BMessage* Result() const { return fResult; }
|
||||||
|
|
||||||
private:
|
static status_t GetPrintServerMessenger(BMessenger& msngr);
|
||||||
void RejectUserInput();
|
|
||||||
void AllowUserInput();
|
|
||||||
void DeleteSemaphore();
|
|
||||||
|
|
||||||
uint32 fWhat;
|
private:
|
||||||
BMessage *fInput;
|
void RejectUserInput();
|
||||||
BMessage *fRequest;
|
void AllowUserInput();
|
||||||
BMessage *fResult;
|
void DeleteSemaphore();
|
||||||
sem_id fThreadCompleted;
|
static status_t MessengerThread(void *data);
|
||||||
BAlert *fHiddenApplicationModalWindow;
|
|
||||||
|
uint32 fWhat;
|
||||||
|
BMessage* fInput;
|
||||||
|
BMessage* fRequest;
|
||||||
|
BMessage* fResult;
|
||||||
|
sem_id fThreadCompleted;
|
||||||
|
BAlert* fHiddenApplicationModalWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Configuration::Configuration(uint32 what, BMessage *input)
|
} // namespace BPrivate
|
||||||
: fWhat(what),
|
using namespace BPrivate;
|
||||||
fInput(input),
|
|
||||||
fRequest(NULL),
|
|
||||||
fResult(NULL),
|
|
||||||
fThreadCompleted(-1),
|
|
||||||
fHiddenApplicationModalWindow(NULL)
|
|
||||||
{
|
|
||||||
RejectUserInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Configuration::~Configuration()
|
// #pragma mark -- BPrintJob
|
||||||
{
|
|
||||||
DeleteSemaphore();
|
|
||||||
// in case SendRequest could not start the thread
|
|
||||||
delete fRequest; fRequest = NULL;
|
|
||||||
AllowUserInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Configuration::RejectUserInput()
|
|
||||||
{
|
|
||||||
BAlert* alert = new BAlert("bogus", "app_modal_dialog", "OK");
|
|
||||||
fHiddenApplicationModalWindow = alert;
|
|
||||||
alert->DefaultButton()->SetEnabled(false);
|
|
||||||
alert->SetDefaultButton(NULL);
|
|
||||||
alert->MoveTo(-65000, -65000);
|
|
||||||
alert->Go(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Configuration::AllowUserInput()
|
|
||||||
{
|
|
||||||
fHiddenApplicationModalWindow->Lock();
|
|
||||||
fHiddenApplicationModalWindow->Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Configuration::DeleteSemaphore()
|
|
||||||
{
|
|
||||||
if (fThreadCompleted >= B_OK) {
|
|
||||||
sem_id id = fThreadCompleted;
|
|
||||||
fThreadCompleted = -1;
|
|
||||||
delete_sem(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Configuration::SendRequest(thread_func function)
|
|
||||||
{
|
|
||||||
fThreadCompleted = create_sem(0, "Configuration");
|
|
||||||
if (fThreadCompleted < B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
thread_id id = spawn_thread(function, "async_request", B_NORMAL_PRIORITY, this);
|
|
||||||
if (id <= 0 || resume_thread(id) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
// Code copied from BAlert::Go()
|
|
||||||
BWindow* window = dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
|
|
||||||
// Get the originating window, if it exists
|
|
||||||
|
|
||||||
// Heavily modified from TextEntryAlert code; the original didn't let the
|
|
||||||
// blocked window ever draw.
|
|
||||||
if (window != NULL) {
|
|
||||||
status_t err;
|
|
||||||
for (;;) {
|
|
||||||
do {
|
|
||||||
err = acquire_sem_etc(fThreadCompleted, 1, B_RELATIVE_TIMEOUT,
|
|
||||||
kSemTimeOut);
|
|
||||||
// We've (probably) had our time slice taken away from us
|
|
||||||
} while (err == B_INTERRUPTED);
|
|
||||||
|
|
||||||
if (err == B_BAD_SEM_ID) {
|
|
||||||
// Semaphore was finally nuked in SetResult(BMessage *)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
window->UpdateIfNeeded();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No window to update, so just hang out until we're done.
|
|
||||||
while (acquire_sem(fThreadCompleted) == B_INTERRUPTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t status;
|
|
||||||
wait_for_thread(id, &status);
|
|
||||||
|
|
||||||
return Result() != NULL ? B_OK : B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMessage *
|
|
||||||
Configuration::Request()
|
|
||||||
{
|
|
||||||
if (fRequest != NULL)
|
|
||||||
return fRequest;
|
|
||||||
|
|
||||||
if (fInput != NULL) {
|
|
||||||
fRequest = new BMessage(*fInput);
|
|
||||||
fRequest->what = fWhat;
|
|
||||||
} else
|
|
||||||
fRequest = new BMessage(fWhat);
|
|
||||||
|
|
||||||
return fRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Configuration::SetResult(BMessage *result)
|
|
||||||
{
|
|
||||||
fResult = result;
|
|
||||||
DeleteSemaphore();
|
|
||||||
// terminate loop in thread spawned by SendRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
} // BPrivate
|
|
||||||
|
|
||||||
|
|
||||||
BPrintJob::BPrintJob(const char *job_name)
|
BPrintJob::BPrintJob(const char *job_name)
|
||||||
@@ -261,93 +153,32 @@ BPrintJob::~BPrintJob()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
ConfigPageThread(void *data)
|
|
||||||
{
|
|
||||||
BPrivate::Configuration* configuration = static_cast<BPrivate::Configuration*>(data);
|
|
||||||
|
|
||||||
BMessenger printServer;
|
|
||||||
if (GetPrinterServerMessenger(printServer) != B_OK) {
|
|
||||||
ShowError(kPrintServerNotRespondingText);
|
|
||||||
configuration->SetResult(NULL);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
BMessage *request = configuration->Request();
|
|
||||||
if (request == NULL) {
|
|
||||||
configuration->SetResult(NULL);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMessage reply;
|
|
||||||
if (printServer.SendMessage(request, &reply) != B_OK
|
|
||||||
|| reply.what != 'okok') {
|
|
||||||
configuration->SetResult(NULL);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration->SetResult(new BMessage(reply));
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPrintJob::ConfigPage()
|
BPrintJob::ConfigPage()
|
||||||
{
|
{
|
||||||
BPrivate::Configuration configuration(PSRV_SHOW_PAGE_SETUP, fSetupMessage);
|
PrintServerMessenger messenger(PSRV_SHOW_PAGE_SETUP, fSetupMessage);
|
||||||
status_t status = configuration.SendRequest(ConfigPageThread);
|
status_t status = messenger.SendRequest();
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
delete fSetupMessage;
|
delete fSetupMessage;
|
||||||
fSetupMessage = configuration.Result();
|
fSetupMessage = messenger.Result();
|
||||||
_HandlePageSetup(fSetupMessage);
|
_HandlePageSetup(fSetupMessage);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
ConfigJobThread(void *data)
|
|
||||||
{
|
|
||||||
BPrivate::Configuration* configuration = static_cast<BPrivate::Configuration*>(data);
|
|
||||||
|
|
||||||
BMessenger printServer;
|
|
||||||
if (GetPrinterServerMessenger(printServer) != B_OK) {
|
|
||||||
ShowError(kPrintServerNotRespondingText);
|
|
||||||
configuration->SetResult(NULL);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
BMessage *request = configuration->Request();
|
|
||||||
if (request == NULL) {
|
|
||||||
configuration->SetResult(NULL);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMessage reply;
|
|
||||||
if (printServer.SendMessage(request, &reply) != B_OK
|
|
||||||
|| reply.what != 'okok') {
|
|
||||||
configuration->SetResult(NULL);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration->SetResult(new BMessage(reply));
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPrintJob::ConfigJob()
|
BPrintJob::ConfigJob()
|
||||||
{
|
{
|
||||||
BPrivate::Configuration configuration(PSRV_SHOW_PRINT_SETUP, fSetupMessage);
|
PrintServerMessenger messenger(PSRV_SHOW_PRINT_SETUP, fSetupMessage);
|
||||||
status_t status = configuration.SendRequest(ConfigJobThread);
|
status_t status = messenger.SendRequest();
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
delete fSetupMessage;
|
delete fSetupMessage;
|
||||||
fSetupMessage = configuration.Result();
|
fSetupMessage = messenger.Result();
|
||||||
_HandlePrintSetup(fSetupMessage);
|
_HandlePrintSetup(fSetupMessage);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -427,7 +258,7 @@ BPrintJob::CommitJob()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (fSpoolFileHeader.page_count == 0) {
|
if (fSpoolFileHeader.page_count == 0) {
|
||||||
ShowError(kNoPagesToPrintText);
|
ShowError("No Pages to print!");
|
||||||
CancelJob();
|
CancelJob();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -465,7 +296,7 @@ BPrintJob::CommitJob()
|
|||||||
|
|
||||||
// notify print server
|
// notify print server
|
||||||
BMessenger printServer;
|
BMessenger printServer;
|
||||||
if (GetPrinterServerMessenger(printServer) != B_OK)
|
if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BMessage request(PSRV_PRINT_SPOOLED_JOB);
|
BMessage request(PSRV_PRINT_SPOOLED_JOB);
|
||||||
@@ -631,12 +462,11 @@ int32
|
|||||||
BPrintJob::PrinterType(void *) const
|
BPrintJob::PrinterType(void *) const
|
||||||
{
|
{
|
||||||
BMessenger printServer;
|
BMessenger printServer;
|
||||||
if (GetPrinterServerMessenger(printServer) != B_OK)
|
if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK)
|
||||||
return B_COLOR_PRINTER; // default
|
return B_COLOR_PRINTER; // default
|
||||||
|
|
||||||
BMessage message(PSRV_GET_ACTIVE_PRINTER);
|
|
||||||
BMessage reply;
|
BMessage reply;
|
||||||
|
BMessage message(PSRV_GET_ACTIVE_PRINTER);
|
||||||
printServer.SendMessage(&message, &reply);
|
printServer.SendMessage(&message, &reply);
|
||||||
|
|
||||||
int32 type;
|
int32 type;
|
||||||
@@ -672,7 +502,7 @@ BPrintJob::_RecurseView(BView *view, BPoint origin, BPicture *picture,
|
|||||||
view->FillRect(rect);
|
view->FillRect(rect);
|
||||||
view->SetHighColor(highColor);
|
view->SetHighColor(highColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
view->Draw(rect);
|
view->Draw(rect);
|
||||||
view->PopState();
|
view->PopState();
|
||||||
view->fIsPrinting = false;
|
view->fIsPrinting = false;
|
||||||
@@ -791,22 +621,23 @@ BPrintJob::_AddPicture(BPicture &picture, BRect &rect, BPoint &where)
|
|||||||
picture.Flatten(fSpoolFile);
|
picture.Flatten(fSpoolFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* !
|
||||||
// Returns a copy of the current printer name
|
*
|
||||||
// or NULL if it could not be obtained.
|
* Returns a copy of the applications default printer name or NULL if it
|
||||||
// Caller is responsible to free the string using free().
|
* could not be obtained. Caller is responsible to free the string using free().
|
||||||
|
*
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
BPrintJob::_GetCurrentPrinterName() const
|
BPrintJob::_GetCurrentPrinterName() const
|
||||||
{
|
{
|
||||||
BMessenger printServer;
|
BMessenger printServer;
|
||||||
if (GetPrinterServerMessenger(printServer))
|
if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
BMessage message(PSRV_GET_ACTIVE_PRINTER);
|
|
||||||
BMessage reply;
|
|
||||||
|
|
||||||
const char *printerName = NULL;
|
const char *printerName = NULL;
|
||||||
|
|
||||||
|
BMessage reply;
|
||||||
|
BMessage message(PSRV_GET_ACTIVE_PRINTER);
|
||||||
if (printServer.SendMessage(&message, &reply) == B_OK)
|
if (printServer.SendMessage(&message, &reply) == B_OK)
|
||||||
reply.FindString("printer_name", &printerName);
|
reply.FindString("printer_name", &printerName);
|
||||||
|
|
||||||
@@ -821,7 +652,7 @@ void
|
|||||||
BPrintJob::_LoadDefaultSettings()
|
BPrintJob::_LoadDefaultSettings()
|
||||||
{
|
{
|
||||||
BMessenger printServer;
|
BMessenger printServer;
|
||||||
if (GetPrinterServerMessenger(printServer) != B_OK)
|
if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BMessage message(PSRV_GET_DEFAULT_SETTINGS);
|
BMessage message(PSRV_GET_DEFAULT_SETTINGS);
|
||||||
@@ -842,3 +673,167 @@ void BPrintJob::_ReservedPrintJob1() {}
|
|||||||
void BPrintJob::_ReservedPrintJob2() {}
|
void BPrintJob::_ReservedPrintJob2() {}
|
||||||
void BPrintJob::_ReservedPrintJob3() {}
|
void BPrintJob::_ReservedPrintJob3() {}
|
||||||
void BPrintJob::_ReservedPrintJob4() {}
|
void BPrintJob::_ReservedPrintJob4() {}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -- PrintServerMessenger
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
|
||||||
|
PrintServerMessenger::PrintServerMessenger(uint32 what, BMessage *input)
|
||||||
|
: fWhat(what),
|
||||||
|
fInput(input),
|
||||||
|
fRequest(NULL),
|
||||||
|
fResult(NULL),
|
||||||
|
fThreadCompleted(-1),
|
||||||
|
fHiddenApplicationModalWindow(NULL)
|
||||||
|
{
|
||||||
|
RejectUserInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PrintServerMessenger::~PrintServerMessenger()
|
||||||
|
{
|
||||||
|
DeleteSemaphore();
|
||||||
|
// in case SendRequest could not start the thread
|
||||||
|
delete fRequest; fRequest = NULL;
|
||||||
|
AllowUserInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PrintServerMessenger::RejectUserInput()
|
||||||
|
{
|
||||||
|
fHiddenApplicationModalWindow = new BAlert("bogus", "app_modal", "OK");
|
||||||
|
fHiddenApplicationModalWindow->DefaultButton()->SetEnabled(false);
|
||||||
|
fHiddenApplicationModalWindow->SetDefaultButton(NULL);
|
||||||
|
fHiddenApplicationModalWindow->MoveTo(-65000, -65000);
|
||||||
|
fHiddenApplicationModalWindow->Go(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PrintServerMessenger::AllowUserInput()
|
||||||
|
{
|
||||||
|
fHiddenApplicationModalWindow->Lock();
|
||||||
|
fHiddenApplicationModalWindow->Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PrintServerMessenger::DeleteSemaphore()
|
||||||
|
{
|
||||||
|
if (fThreadCompleted >= B_OK) {
|
||||||
|
sem_id id = fThreadCompleted;
|
||||||
|
fThreadCompleted = -1;
|
||||||
|
delete_sem(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PrintServerMessenger::SendRequest()
|
||||||
|
{
|
||||||
|
fThreadCompleted = create_sem(0, "print_server_messenger_sem");
|
||||||
|
if (fThreadCompleted < B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
thread_id id = spawn_thread(MessengerThread, "async_request",
|
||||||
|
B_NORMAL_PRIORITY, this);
|
||||||
|
if (id <= 0 || resume_thread(id) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// Get the originating window, if it exists
|
||||||
|
BWindow* window = dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
|
||||||
|
if (window) {
|
||||||
|
status_t err;
|
||||||
|
while (true) {
|
||||||
|
do {
|
||||||
|
err = acquire_sem_etc(fThreadCompleted, 1, B_RELATIVE_TIMEOUT,
|
||||||
|
50000);
|
||||||
|
// We've (probably) had our time slice taken away from us
|
||||||
|
} while (err == B_INTERRUPTED);
|
||||||
|
|
||||||
|
// Semaphore was finally nuked in SetResult(BMessage *)
|
||||||
|
if (err == B_BAD_SEM_ID)
|
||||||
|
break;
|
||||||
|
window->UpdateIfNeeded();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No window to update, so just hang out until we're done.
|
||||||
|
while (acquire_sem(fThreadCompleted) == B_INTERRUPTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t status;
|
||||||
|
wait_for_thread(id, &status);
|
||||||
|
|
||||||
|
return Result() != NULL ? B_OK : B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage *
|
||||||
|
PrintServerMessenger::Request()
|
||||||
|
{
|
||||||
|
if (fRequest != NULL)
|
||||||
|
return fRequest;
|
||||||
|
|
||||||
|
if (fInput != NULL) {
|
||||||
|
fRequest = new BMessage(*fInput);
|
||||||
|
fRequest->what = fWhat;
|
||||||
|
} else
|
||||||
|
fRequest = new BMessage(fWhat);
|
||||||
|
|
||||||
|
return fRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PrintServerMessenger::SetResult(BMessage *result)
|
||||||
|
{
|
||||||
|
fResult = result;
|
||||||
|
DeleteSemaphore();
|
||||||
|
// terminate loop in thread spawned by SendRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PrintServerMessenger::GetPrintServerMessenger(BMessenger& messenger)
|
||||||
|
{
|
||||||
|
messenger = BMessenger(PSRV_SIGNATURE_TYPE);
|
||||||
|
return messenger.IsValid() ? B_OK : B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PrintServerMessenger::MessengerThread(void *data)
|
||||||
|
{
|
||||||
|
PrintServerMessenger* messenger = static_cast<PrintServerMessenger*>(data);
|
||||||
|
|
||||||
|
BMessenger printServer;
|
||||||
|
if (messenger->GetPrintServerMessenger(printServer) != B_OK) {
|
||||||
|
ShowError("Print Server is not responding.");
|
||||||
|
messenger->SetResult(NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessage *request = messenger->Request();
|
||||||
|
if (request == NULL) {
|
||||||
|
messenger->SetResult(NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage reply;
|
||||||
|
if (printServer.SendMessage(request, &reply) != B_OK
|
||||||
|
|| reply.what != 'okok') {
|
||||||
|
messenger->SetResult(NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
messenger->SetResult(new BMessage(reply));
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|||||||
Reference in New Issue
Block a user