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
27struct AsyncThreadParams {
28	PrintServerApp* app;
29	Printer* printer;
30	BMessage* message;
31
32	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
41	~AsyncThreadParams() {
42		if (printer) printer->Release();
43		delete message;
44		app->Release();
45	}
46
47	BMessage* AcquireMessage() {
48		BMessage* m = message; message = NULL; return m;
49	}
50};
51
52
53status_t
54PrintServerApp::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
161void
162PrintServerApp::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
177void
178PrintServerApp::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