1 /*
2 * Copyright 2001-2008, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Ithamar R. Adema
7 * Michael Pfeiffer
8 */
9 #include "PrintServerApp.h"
10
11 #include "pr_server.h"
12 #include "Printer.h"
13 #include "ConfigWindow.h"
14
15 // BeOS API
16 #include <Alert.h>
17 #include <Autolock.h>
18 #include <Catalog.h>
19 #include <Locale.h>
20 #include <PrintJob.h>
21
22
23 #undef B_TRANSLATION_CONTEXT
24 #define B_TRANSLATION_CONTEXT "PrintServerApp"
25
26
27 struct AsyncThreadParams {
28 PrintServerApp* app;
29 Printer* printer;
30 BMessage* message;
31
AsyncThreadParamsAsyncThreadParams32 AsyncThreadParams(PrintServerApp* app, Printer* p, BMessage* m)
33 : app(app)
34 , printer(p)
35 , message(m)
36 {
37 app->Acquire();
38 if (printer) printer->Acquire();
39 }
40
~AsyncThreadParamsAsyncThreadParams41 ~AsyncThreadParams() {
42 if (printer) printer->Release();
43 delete message;
44 app->Release();
45 }
46
AcquireMessageAsyncThreadParams47 BMessage* AcquireMessage() {
48 BMessage* m = message; message = NULL; return m;
49 }
50 };
51
52
53 status_t
async_thread(void * data)54 PrintServerApp::async_thread(void* data)
55 {
56 AsyncThreadParams* p = (AsyncThreadParams*)data;
57
58 Printer* printer = p->printer;
59 BMessage* msg = p->AcquireMessage();
60 {
61 AutoReply sender(msg, 'stop');
62 switch (msg->what) {
63 // Handle showing the config dialog
64 case PSRV_SHOW_PAGE_SETUP: {
65 case PSRV_SHOW_PRINT_SETUP:
66 if (printer) {
67 if (p->app->fUseConfigWindow) {
68 config_setup_kind kind = kJobSetup;
69 if (msg->what == PSRV_SHOW_PAGE_SETUP)
70 kind = kPageSetup;
71 ConfigWindow* w = new ConfigWindow(kind, printer, msg,
72 &sender);
73 w->Go();
74 } else {
75 BMessage reply(*msg);
76 status_t status = B_ERROR;
77 if (msg->what == PSRV_SHOW_PAGE_SETUP)
78 status = printer->ConfigurePage(reply);
79 else
80 status = printer->ConfigureJob(reply);
81
82 if (status == B_OK)
83 sender.SetReply(&reply);
84 }
85 } else {
86 // If no default printer is set, give user
87 // choice of aborting or setting up a printer
88 int32 count = Printer::CountPrinters();
89 BString alertText(
90 B_TRANSLATE("There are no printers set up."));
91 if (count > 0)
92 alertText.SetTo(B_TRANSLATE(
93 "There is no default printer set up."));
94
95 alertText.Append(" ");
96 alertText.Append(
97 B_TRANSLATE("Would you like to set one up now?"));
98 BAlert* alert = new BAlert("Info", alertText.String(),
99 B_TRANSLATE("No"), B_TRANSLATE("Yes"));
100 alert->SetShortcut(0, B_ESCAPE);
101 if (alert->Go() == 1) {
102 if (count == 0)
103 run_add_printer_panel();
104 else
105 run_select_printer_panel();
106 }
107 }
108 } break;
109
110 // Retrieve default configuration message from printer add-on
111 case PSRV_GET_DEFAULT_SETTINGS: {
112 if (printer) {
113 BMessage reply;
114 if (printer->GetDefaultSettings(reply) == B_OK) {
115 sender.SetReply(&reply);
116 break;
117 }
118 }
119 } break;
120
121 // Create a new printer
122 case PSRV_MAKE_PRINTER: {
123 BString driverName;
124 BString printerName;
125 BString transportName;
126 BString transportPath;
127 if (msg->FindString("driver", &driverName) == B_OK
128 && msg->FindString("transport", &transportName) == B_OK
129 && msg->FindString("transport path", &transportPath) == B_OK
130 && msg->FindString("printer name", &printerName) == B_OK) {
131 BString connection;
132 if (msg->FindString("connection", &connection) != B_OK)
133 connection = "Local";
134
135 // then create the actual printer
136 if (p->app->CreatePrinter(printerName.String(),
137 driverName.String(), connection.String(),
138 transportName.String(),
139 transportPath.String()) == B_OK) {
140 // If printer was created ok,
141 // ask if it needs to be the default
142 BString text(B_TRANSLATE("Would you like to make @ "
143 "the default printer?"));
144 text.ReplaceFirst("@", printerName.String());
145 BAlert* alert = new BAlert("", text.String(),
146 B_TRANSLATE("No"), B_TRANSLATE("Yes"));
147 alert->SetShortcut(0, B_ESCAPE);
148 if (alert->Go() == 1)
149 p->app->SelectPrinter(printerName.String());
150 }
151 }
152 } break;
153 }
154 }
155 delete p;
156 return B_OK;
157 }
158
159
160 // Async. processing of received message
161 void
AsyncHandleMessage(BMessage * msg)162 PrintServerApp::AsyncHandleMessage(BMessage* msg)
163 {
164 AsyncThreadParams* data = new AsyncThreadParams(this, fDefaultPrinter, msg);
165
166 thread_id tid = spawn_thread(async_thread, "async", B_NORMAL_PRIORITY,
167 (void*)data);
168
169 if (tid > 0) {
170 resume_thread(tid);
171 } else {
172 delete data;
173 }
174 }
175
176
177 void
Handle_BeOSR5_Message(BMessage * msg)178 PrintServerApp::Handle_BeOSR5_Message(BMessage* msg)
179 {
180 switch(msg->what) {
181 // Get currently selected printer
182 case PSRV_GET_ACTIVE_PRINTER: {
183 BMessage reply('okok');
184 BString printerName;
185 if (fDefaultPrinter)
186 printerName = fDefaultPrinter->Name();
187 BString mime;
188 if (fUseConfigWindow && MimeTypeForSender(msg, mime)) {
189 BAutolock lock(gLock);
190 if (lock.IsLocked()) {
191 // override with printer for application
192 PrinterSettings* p = fSettings->FindPrinterSettings(
193 mime.String());
194 if (p)
195 printerName = p->GetPrinter();
196 }
197 }
198 reply.AddString("printer_name", printerName);
199 // BeOS knows not if color or not, so always color
200 reply.AddInt32("color", BPrintJob::B_COLOR_PRINTER);
201 msg->SendReply(&reply);
202 }
203 break;
204
205 //make printer active (currently always quietly :))
206 case PSRV_MAKE_PRINTER_ACTIVE_QUIETLY:
207 //make printer active quietly
208 case PSRV_MAKE_PRINTER_ACTIVE: {
209 BString newActivePrinter;
210 if (msg->FindString("printer",&newActivePrinter) == B_OK) {
211 SelectPrinter(newActivePrinter.String());
212 }
213 }
214 break;
215
216 case PSRV_SHOW_PAGE_SETUP:
217 case PSRV_SHOW_PRINT_SETUP:
218 case PSRV_GET_DEFAULT_SETTINGS:
219 case PSRV_MAKE_PRINTER:
220 AsyncHandleMessage(DetachCurrentMessage());
221 break;
222
223 // Tell printer addon to print a spooled job
224 case PSRV_PRINT_SPOOLED_JOB:
225 HandleSpooledJobs();
226 break;
227 }
228 }
229
230