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 { 160 fOutputStream = outputStream; 161 fJob.SetApplicationName("Gutenprint"); 162 fJob.SetConfiguration(configuration); 163 fJob.SetOutputStream(outputStream); 164 165 return fJob.Begin(); 166 } 167 168 169 void 170 GPBinding::EndJob() 171 { 172 fJob.End(); 173 fOutputStream = NULL; 174 } 175 176 177 void 178 GPBinding::BeginPage() 179 { 180 } 181 182 183 void 184 GPBinding::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 198 status_t 199 GPBinding::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 211 void 212 GPBinding::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 225 void 226 GPBinding::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