1 /* 2 * Copyright 2008 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Julun, <host.haiku@gmx.de 7 */ 8 9 #include <Printer.h> 10 11 #include <FindDirectory.h> 12 #include <NodeInfo.h> 13 #include <NodeMonitor.h> 14 15 16 #include <new> 17 18 19 namespace BPrivate { 20 namespace Print { 21 22 23 // TODO: remove, after pr_server.h cleanup 24 25 // mime file types 26 #define PSRV_PRINTER_MIMETYPE "application/x-vnd.Be.printer" 27 28 29 // printer attributes 30 #define PSRV_PRINTER_ATTR_STATE "state" 31 #define PSRV_PRINTER_ATTR_COMMENTS "Comments" 32 #define PSRV_PRINTER_ATTR_TRANSPORT "transport" 33 #define PSRV_PRINTER_ATTR_DRIVER_NAME "Driver Name" 34 #define PSRV_PRINTER_ATTR_PRINTER_NAME "Printer Name" 35 #define PSRV_PRINTER_ATTR_DEFAULT_PRINTER "Default Printer" 36 #define PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS "transport_address" 37 38 39 // message fields 40 #define PSRV_FIELD_CURRENT_PRINTER "current_printer" 41 42 43 BPrinter::BPrinter() 44 : fListener(NULL) 45 { 46 memset(&fPrinterEntryRef, 0, sizeof(entry_ref)); 47 } 48 49 50 BPrinter::BPrinter(const BEntry& entry) 51 : fListener(NULL) 52 { 53 SetTo(entry); 54 } 55 56 57 BPrinter::BPrinter(const BPrinter& printer) 58 { 59 *this = printer; 60 } 61 62 63 BPrinter::BPrinter(const node_ref& nodeRef) 64 : fListener(NULL) 65 { 66 SetTo(nodeRef); 67 } 68 69 70 BPrinter::BPrinter(const entry_ref& entryRef) 71 : fListener(NULL) 72 , fPrinterEntryRef(entryRef) 73 { 74 } 75 76 77 BPrinter::BPrinter(const BDirectory& directory) 78 : fListener(NULL) 79 { 80 SetTo(directory); 81 } 82 83 84 BPrinter::~BPrinter() 85 { 86 StopWatching(); 87 } 88 89 90 status_t 91 BPrinter::SetTo(const BEntry& entry) 92 { 93 StopWatching(); 94 entry.GetRef(&fPrinterEntryRef); 95 96 return InitCheck(); 97 } 98 99 100 status_t 101 BPrinter::SetTo(const node_ref& nodeRef) 102 { 103 SetTo(BDirectory(&nodeRef)); 104 return InitCheck(); 105 } 106 107 108 status_t 109 BPrinter::SetTo(const entry_ref& entryRef) 110 { 111 StopWatching(); 112 fPrinterEntryRef = entryRef; 113 114 return InitCheck(); 115 } 116 117 118 status_t 119 BPrinter::SetTo(const BDirectory& directory) 120 { 121 StopWatching(); 122 123 BEntry entry; 124 directory.GetEntry(&entry); 125 entry.GetRef(&fPrinterEntryRef); 126 127 return InitCheck(); 128 } 129 130 131 void 132 BPrinter::Unset() 133 { 134 StopWatching(); 135 memset(&fPrinterEntryRef, 0, sizeof(entry_ref)); 136 } 137 138 139 bool 140 BPrinter::IsValid() const 141 { 142 BDirectory spoolDir(&fPrinterEntryRef); 143 if (spoolDir.InitCheck() != B_OK) 144 return false; 145 146 BNode node(spoolDir); 147 char type[B_MIME_TYPE_LENGTH]; 148 BNodeInfo(&node).GetType(type); 149 150 if (strcmp(type, PSRV_PRINTER_MIMETYPE) != 0) 151 return false; 152 153 return true; 154 } 155 156 157 status_t 158 BPrinter::InitCheck() const 159 { 160 BDirectory spoolDir(&fPrinterEntryRef); 161 return spoolDir.InitCheck(); 162 } 163 164 165 bool 166 BPrinter::IsFree() const 167 { 168 return (State() == "free"); 169 } 170 171 172 bool 173 BPrinter::IsDefault() const 174 { 175 bool isDefault = false; 176 177 BDirectory spoolDir(&fPrinterEntryRef); 178 if (spoolDir.InitCheck() == B_OK) 179 spoolDir.ReadAttr(PSRV_PRINTER_ATTR_DEFAULT_PRINTER, B_BOOL_TYPE, 0, 180 &isDefault, sizeof(bool)); 181 182 return isDefault; 183 } 184 185 186 bool 187 BPrinter::IsShareable() const 188 { 189 if (Name() == "Preview") 190 return true; 191 192 return false; 193 } 194 195 196 BString 197 BPrinter::Name() const 198 { 199 return _ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME); 200 } 201 202 203 BString 204 BPrinter::State() const 205 { 206 return _ReadAttribute(PSRV_PRINTER_ATTR_STATE); 207 } 208 209 210 BString 211 BPrinter::Driver() const 212 { 213 return _ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME); 214 } 215 216 217 BString 218 BPrinter::Comments() const 219 { 220 return _ReadAttribute(PSRV_PRINTER_ATTR_COMMENTS); 221 } 222 223 224 BString 225 BPrinter::Transport() const 226 { 227 return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT); 228 } 229 230 231 BString 232 BPrinter::TransportAddress() const 233 { 234 return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS); 235 } 236 237 238 status_t 239 BPrinter::DefaultSettings(BMessage& settings) 240 { 241 status_t status = B_ERROR; 242 image_id id = _LoadDriver(); 243 if (id < 0) 244 return status; 245 246 typedef BMessage* (*default_settings_func_t)(BNode*); 247 default_settings_func_t default_settings; 248 if (get_image_symbol(id, "default_settings", B_SYMBOL_TYPE_TEXT 249 , (void**)&default_settings) == B_OK) { 250 BNode printerNode(&fPrinterEntryRef); 251 BMessage *newSettings = default_settings(&printerNode); 252 if (newSettings) { 253 status = B_OK; 254 settings = *newSettings; 255 _AddPrinterName(settings); 256 } 257 delete newSettings; 258 } 259 unload_add_on(id); 260 return status; 261 } 262 263 264 status_t 265 BPrinter::StartWatching(const BMessenger& listener) 266 { 267 StopWatching(); 268 269 if (!listener.IsValid()) 270 return B_BAD_VALUE; 271 272 fListener = new(std::nothrow) BMessenger(listener); 273 if (!fListener) 274 return B_NO_MEMORY; 275 276 node_ref nodeRef; 277 nodeRef.device = fPrinterEntryRef.device; 278 nodeRef.node = fPrinterEntryRef.directory; 279 280 return watch_node(&nodeRef, B_WATCH_DIRECTORY, *fListener); 281 } 282 283 284 void 285 BPrinter::StopWatching() 286 { 287 if (fListener) { 288 stop_watching(*fListener); 289 delete fListener; 290 fListener = NULL; 291 } 292 } 293 294 295 BPrinter& 296 BPrinter::operator=(const BPrinter& printer) 297 { 298 if (this != &printer) { 299 Unset(); 300 fPrinterEntryRef = printer.fPrinterEntryRef; 301 if (printer.fListener) 302 StartWatching(*printer.fListener); 303 } 304 return *this; 305 } 306 307 308 bool 309 BPrinter::operator==(const BPrinter& printer) const 310 { 311 return (fPrinterEntryRef == printer.fPrinterEntryRef); 312 } 313 314 315 bool 316 BPrinter::operator!=(const BPrinter& printer) const 317 { 318 return (fPrinterEntryRef != printer.fPrinterEntryRef); 319 } 320 321 322 status_t 323 BPrinter::_Configure() const 324 { 325 status_t status = B_ERROR; 326 image_id id = _LoadDriver(); 327 if (id < 0) 328 return status; 329 330 BString printerName(_ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME)); 331 if (printerName.Length() > 0) { 332 typedef char* (*add_printer_func_t)(const char*); 333 add_printer_func_t add_printer; 334 if (get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT 335 , (void**)&add_printer) == B_OK) { 336 if (add_printer(printerName.String()) != NULL) 337 status = B_OK; 338 } 339 } else { 340 status = B_ERROR; 341 } 342 unload_add_on(id); 343 return status; 344 } 345 346 347 status_t 348 BPrinter::_ConfigureJob(BMessage& settings) 349 { 350 status_t status = B_ERROR; 351 image_id id = _LoadDriver(); 352 if (id < 0) 353 return status; 354 355 typedef BMessage* (*config_job_func_t)(BNode*, const BMessage*); 356 config_job_func_t configure_job; 357 if (get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT 358 , (void**)&configure_job) == B_OK) { 359 BNode printerNode(&fPrinterEntryRef); 360 BMessage *newSettings = configure_job(&printerNode, &settings); 361 if (newSettings && (newSettings->what == 'okok')) { 362 status = B_OK; 363 settings = *newSettings; 364 _AddPrinterName(settings); 365 } 366 delete newSettings; 367 } 368 unload_add_on(id); 369 return status; 370 } 371 372 373 status_t 374 BPrinter::_ConfigurePage(BMessage& settings) 375 { 376 status_t status = B_ERROR; 377 image_id id = _LoadDriver(); 378 if (id < 0) 379 return status; 380 381 typedef BMessage* (*config_page_func_t)(BNode*, const BMessage*); 382 config_page_func_t configure_page; 383 if (get_image_symbol(id, "config_page", B_SYMBOL_TYPE_TEXT 384 , (void**)&configure_page) == B_OK) { 385 BNode printerNode(&fPrinterEntryRef); 386 BMessage *newSettings = configure_page(&printerNode, &settings); 387 if (newSettings && (newSettings->what == 'okok')) { 388 status = B_OK; 389 settings = *newSettings; 390 _AddPrinterName(settings); 391 } 392 delete newSettings; 393 } 394 unload_add_on(id); 395 return status; 396 } 397 398 399 BPath 400 BPrinter::_DriverPath() const 401 { 402 BString driverName(_ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME)); 403 if (driverName.Length() <= 0) 404 return BPath(); 405 406 directory_which directories[] = { 407 B_USER_NONPACKAGED_ADDONS_DIRECTORY, 408 B_USER_ADDONS_DIRECTORY, 409 B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY, 410 B_SYSTEM_ADDONS_DIRECTORY 411 }; 412 413 BPath path; 414 driverName.Prepend("Print/"); 415 for (int32 i = 0; i < sizeof(directories) / sizeof(directories[0]); ++i) { 416 if (find_directory(directories[i], &path) == B_OK) { 417 path.Append(driverName.String()); 418 419 BEntry driver(path.Path()); 420 if (driver.InitCheck() == B_OK && driver.Exists() && driver.IsFile()) 421 return path; 422 } 423 } 424 return BPath(); 425 } 426 427 428 image_id 429 BPrinter::_LoadDriver() const 430 { 431 BPath driverPath(_DriverPath()); 432 if (driverPath.InitCheck() != B_OK) 433 return -1; 434 435 return load_add_on(driverPath.Path()); 436 } 437 438 439 void 440 BPrinter::_AddPrinterName(BMessage& settings) 441 { 442 settings.RemoveName(PSRV_FIELD_CURRENT_PRINTER); 443 settings.AddString(PSRV_FIELD_CURRENT_PRINTER, Name()); 444 } 445 446 447 BString 448 BPrinter::_ReadAttribute(const char* attribute) const 449 { 450 BString value; 451 452 BDirectory spoolDir(&fPrinterEntryRef); 453 if (spoolDir.InitCheck() == B_OK) 454 spoolDir.ReadAttrString(attribute, &value); 455 456 return value; 457 } 458 459 460 } // namespace Print 461 } // namespace BPrivate 462