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 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 53 status_t 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 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 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