1/* 2* Copyright 2010, Haiku. All rights reserved. 3* Distributed under the terms of the MIT License. 4* 5* Authors: 6* Michael Pfeiffer 7*/ 8#include "GPBinding.h" 9 10#include <list> 11#include <set> 12#include <string> 13 14#include <gutenprint/gutenprint.h> 15 16 17#include "GPCapabilityExtractor.h" 18 19using namespace std; 20 21 22// printer manufacturer 23static const char* kManufacturerId = "id"; 24static const char* kManufacturerDisplayName = "name"; 25 26// printer model 27static const char* kModelDisplayName = "model"; 28static const char* kModelDriver = "driver"; 29 30 31GPBinding::GPBinding() 32: 33fInitialized(false), 34fOutputStream(NULL) 35{ 36 37} 38 39 40GPBinding::~GPBinding() 41{ 42 DeleteBands(); 43} 44 45 46status_t 47GPBinding::GetPrinterManufacturers(BMessage& manufacturers) 48{ 49 InitGutenprint(); 50 51 list<string> ids; 52 set<string> manufacturerSet; 53 54 for (int i = 0; i < stp_printer_model_count(); i ++) { 55 const stp_printer_t* printer = stp_get_printer_by_index(i); 56 string manufacturer = stp_printer_get_manufacturer(printer); 57 58 // ignore unnamed manufacturers 59 if (manufacturer == "") 60 continue; 61 62 // add manufacturer only once 63 if (manufacturerSet.find(manufacturer) != manufacturerSet.end()) 64 continue; 65 66 manufacturerSet.insert(manufacturer); 67 68 ids.push_back(manufacturer); 69 } 70 71 ids.sort(); 72 73 list<string>::iterator it = ids.begin(); 74 for (; it != ids.end(); it ++) { 75 string manufacturer = *it; 76 const char* id = manufacturer.c_str(); 77 const char* name = manufacturer.c_str(); 78 AddManufacturer(manufacturers, id, name); 79 } 80 return B_OK; 81} 82 83 84bool 85GPBinding::ExtractManufacturer(const BMessage& manufacturers, int32 index, 86 BString& id, BString& displayName) 87{ 88 if (manufacturers.FindString(kManufacturerId, index, &id) != B_OK) 89 return false; 90 if (manufacturers.FindString(kManufacturerDisplayName, index, &displayName) 91 != B_OK) 92 return false; 93 return true; 94} 95 96 97void 98GPBinding::AddManufacturer(BMessage& manufacturers, const char* id, 99 const char* displayName) 100{ 101 manufacturers.AddString(kManufacturerId, id); 102 manufacturers.AddString(kManufacturerDisplayName, displayName); 103} 104 105 106status_t 107GPBinding::GetPrinterModels(const char* manufacturer, BMessage& models) 108{ 109 for (int i = 0; i < stp_printer_model_count(); i ++) { 110 const stp_printer_t* printer = stp_get_printer_by_index(i); 111 if (strcmp(manufacturer, stp_printer_get_manufacturer(printer)) != 0) 112 continue; 113 114 const char* displayName = stp_printer_get_long_name(printer); 115 const char* driver = stp_printer_get_driver(printer); 116 AddModel(models, displayName, driver); 117 } 118 return B_OK; 119} 120 121 122bool 123GPBinding::ExtractModel(const BMessage& models, int32 index, BString& displayName, 124 BString& driver) 125{ 126 if (models.FindString(kModelDisplayName, index, &displayName) != B_OK) 127 return false; 128 if (models.FindString(kModelDriver, index, &driver) != B_OK) 129 return false; 130 return true; 131} 132 133 134void 135GPBinding::AddModel(BMessage& models, const char* displayName, const char* driver) 136{ 137 models.AddString(kModelDisplayName, displayName); 138 models.AddString(kModelDriver, driver); 139} 140 141 142status_t 143GPBinding::GetCapabilities(const char* driver, GPCapabilities* capabilities) 144{ 145 InitGutenprint(); 146 const stp_printer_t* printer = stp_get_printer_by_driver(driver); 147 if (printer == NULL) 148 return B_ERROR; 149 150 GPCapabilityExtractor extractor(capabilities); 151 extractor.Visit(printer); 152 return B_OK; 153} 154 155 156status_t 157GPBinding::BeginJob(GPJobConfiguration* configuration, 158 OutputStream* outputStream) 159{ 160 fOutputStream = outputStream; 161 fJob.SetApplicationName("Gutenprint"); 162 fJob.SetConfiguration(configuration); 163 fJob.SetOutputStream(outputStream); 164 165 return fJob.Begin(); 166} 167 168 169void 170GPBinding::EndJob() 171{ 172 fJob.End(); 173 fOutputStream = NULL; 174} 175 176 177void 178GPBinding::BeginPage() 179{ 180} 181 182 183void 184GPBinding::EndPage() 185{ 186 status_t status = fJob.PrintPage(fBands); 187 DeleteBands(); 188 if (status == B_IO_ERROR) 189 throw TransportException("I/O Error"); 190 if (status == B_ERROR) { 191 BString message; 192 fJob.GetErrorMessage(message); 193 throw TransportException(message.String()); 194 } 195} 196 197 198status_t 199GPBinding::AddBitmapToPage(BBitmap* bitmap, BRect validRect, BPoint where) 200{ 201 GPBand* band = new(nothrow) GPBand(bitmap, validRect, where); 202 if (band == NULL) { 203 return B_NO_MEMORY; 204 } 205 206 fBands.push_back(band); 207 return B_OK; 208} 209 210 211void 212GPBinding::InitGutenprint() 213{ 214 if (fInitialized) 215 return; 216 fInitialized = true; 217 // there is no "destroy" counter part so this creates memory leaks 218 // this is no problem because the print server loads printer add-ons 219 // in a new application instance that is terminated when not used anymore 220 stp_init(); 221 stp_set_output_codeset("UTF-8"); 222} 223 224 225void 226GPBinding::DeleteBands() 227{ 228 list<GPBand*>::iterator it = fBands.begin(); 229 for (; it != fBands.end(); it ++) { 230 GPBand* band = *it; 231 delete band; 232 } 233 fBands.clear(); 234} 235