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 19 using namespace std; 20 21 22 // printer manufacturer 23 static const char* kManufacturerId = "id"; 24 static const char* kManufacturerDisplayName = "name"; 25 26 // printer model 27 static const char* kModelDisplayName = "model"; 28 static const char* kModelDriver = "driver"; 29 30 31 GPBinding::GPBinding() 32 : 33 fInitialized(false), 34 fOutputStream(NULL) 35 { 36 37 } 38 39 40 GPBinding::~GPBinding() 41 { 42 DeleteBands(); 43 } 44 45 46 status_t 47 GPBinding::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 84 bool 85 GPBinding::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 97 void 98 GPBinding::AddManufacturer(BMessage& manufacturers, const char* id, 99 const char* displayName) 100 { 101 manufacturers.AddString(kManufacturerId, id); 102 manufacturers.AddString(kManufacturerDisplayName, displayName); 103 } 104 105 106 status_t 107 GPBinding::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 122 bool 123 GPBinding::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 134 void 135 GPBinding::AddModel(BMessage& models, const char* displayName, const char* driver) 136 { 137 models.AddString(kModelDisplayName, displayName); 138 models.AddString(kModelDriver, driver); 139 } 140 141 142 status_t 143 GPBinding::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 156 status_t 157 GPBinding::BeginJob(GPJobConfiguration* configuration, 158 OutputStream* outputStream) 159 throw(TransportException) 160 { 161 fOutputStream = outputStream; 162 fJob.SetApplicationName("Gutenprint"); 163 fJob.SetConfiguration(configuration); 164 fJob.SetOutputStream(outputStream); 165 166 return fJob.Begin(); 167 } 168 169 170 void 171 GPBinding::EndJob() throw(TransportException) 172 { 173 fJob.End(); 174 fOutputStream = NULL; 175 } 176 177 178 void 179 GPBinding::BeginPage() throw(TransportException) 180 { 181 } 182 183 184 void 185 GPBinding::EndPage() throw(TransportException) 186 { 187 status_t status = fJob.PrintPage(fBands); 188 DeleteBands(); 189 if (status == B_IO_ERROR) 190 throw TransportException("I/O Error"); 191 if (status == B_ERROR) { 192 BString message; 193 fJob.GetErrorMessage(message); 194 throw TransportException(message.String()); 195 } 196 } 197 198 199 status_t 200 GPBinding::AddBitmapToPage(BBitmap* bitmap, BRect validRect, BPoint where) 201 { 202 GPBand* band = new(nothrow) GPBand(bitmap, validRect, where); 203 if (band == NULL) { 204 return B_NO_MEMORY; 205 } 206 207 fBands.push_back(band); 208 return B_OK; 209 } 210 211 212 void 213 GPBinding::InitGutenprint() 214 { 215 if (fInitialized) 216 return; 217 fInitialized = true; 218 // there is no "destroy" counter part so this creates memory leaks 219 // this is no problem because the print server loads printer add-ons 220 // in a new application instance that is terminated when not used anymore 221 stp_init(); 222 stp_set_output_codeset("UTF-8"); 223 } 224 225 226 void 227 GPBinding::DeleteBands() 228 { 229 list<GPBand*>::iterator it = fBands.begin(); 230 for (; it != fBands.end(); it ++) { 231 GPBand* band = *it; 232 delete band; 233 } 234 fBands.clear(); 235 } 236